Spring Boot JPA - mengonfigurasi sambungan ulang otomatis


107

Saya memiliki aplikasi web JPA Spring Boot kecil yang bagus. Ini diterapkan di Amazon Beanstalk dan menggunakan Amazon RDS untuk menyimpan data. Namun itu tidak sering digunakan dan karena itu gagal setelah beberapa saat dengan pengecualian semacam ini:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Paket terakhir yang berhasil diterima dari server adalah 79.870.633 milidetik yang lalu.
Paket terakhir yang berhasil dikirim ke server adalah 79.870.634 milidetik yang lalu. lebih panjang dari nilai 'wait_timeout' yang dikonfigurasi server. Anda harus mempertimbangkan untuk kedaluwarsa dan / atau menguji validitas koneksi sebelum digunakan dalam aplikasi Anda, meningkatkan nilai konfigurasi server untuk waktu tunggu klien, atau menggunakan properti koneksi Connector / J 'autoReconnect = true' untuk menghindari masalah ini.

Saya tidak yakin bagaimana mengkonfigurasi pengaturan ini dan tidak dapat menemukan informasi tentangnya di http://spring.io (meskipun situs yang sangat bagus). Apa sajakah ide atau petunjuk untuk informasi?


Gunakan ini untuk mencetak Anda DataSourcedan memverifikasi propertinya. stackoverflow.com/a/36586630/148844 Spring Boot tidak akan mengkonfigurasi secara otomatis DataSourcejika Anda memiliki @Beansfile DataSource. docs.spring.io/spring-boot/docs/1.5.16.RELEASE/reference/…
Chloe

Jawaban:


141

Saya berasumsi bahwa boot sedang mengkonfigurasi DataSourceuntuk Anda. Dalam hal ini, dan karena Anda menggunakan MySQL, Anda dapat menambahkan yang berikut ini ke application.propertieshingga 1.3 Anda

spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1

Seperti djxak dicatat dalam komentar, 1.4 + mendefinisikan ruang nama khusus untuk empat koneksi kolam Musim Semi Boot mendukung: tomcat, hikari, dbcp, dbcp2( dbcpsudah ditinggalkan sebagai 1,5). Anda perlu memeriksa kumpulan koneksi mana yang Anda gunakan dan memeriksa apakah fitur itu didukung. Contoh di atas adalah untuk kucing jantan jadi Anda harus menuliskannya sebagai berikut di 1.4+:

spring.datasource.tomcat.testOnBorrow=true 
spring.datasource.tomcat.validationQuery=SELECT 1

Perhatikan bahwa penggunaan autoReconnectyang tidak dianjurkan :

Penggunaan fitur ini tidak disarankan, karena memiliki efek samping terkait status sesi dan konsistensi data saat aplikasi tidak menangani SQLExceptions dengan benar, dan hanya dirancang untuk digunakan saat Anda tidak dapat mengonfigurasi aplikasi Anda untuk menangani SQLExceptions yang dihasilkan dari koneksi mati dan basi dengan benar.


8
itu karena kami telah menyelaraskan cara kami menulis kunci dalam dokumentasi. Kami selalu menggunakan pengikat santai sehingga keduanya spring.datasource.testOnBorrowdan spring.datasource.test-on-borrowakan bekerja dengan baik. Lihat dokumentasi untuk lebih jelasnya.
Stephane Nicoll

17
Karena dapat membingungkan orang lain: SELECT 1menjamin bahwa koneksi telah diuji sebelum diserahkan ke aplikasi. Dengan menggunakan testOnBorrow = true, objek akan divalidasi sebelum dipinjam dari pool. Jika objek gagal divalidasi, itu akan dihapus dari kumpulan, dan akan mencoba untuk meminjam yang lain. CATATAN - agar nilai benar memiliki efek, parameter validationQuery harus disetel ke string bukan nol.
Rick

14
Peringatan! Di Spring Boot 1.4 + ini berubah : ada didefinisikan ruang nama tertentu baru untuk empat koneksi kolam air mendukung: tomcat, hikari, dbcp, dbcp2. Jadi, misalnya, untuk tomcat-jdbcconnection-pool, propertinya harus: spring.datasource.tomcat.testOnBorrow=truedan spring.datasource.tomcat.validationQuery=SELECT 1.
Ruslan Stelmachenko

1
Jika saya sendiri mengonfigurasi dua sumber data yang berbeda, lalu bagaimana cara memberikan konfigurasi ini? Apakah saya perlu memberikan konfigurasi ini untuk kedua sumber data seperti spring.datasource.mydatasource1.tomcat.testOnBorrow = true spring.datasource.mydatasource1.tomcat.validationQuery = SELECT 1 spring.datasource.mydatasource2.tomcat.testOnBorrow = true spring.datasource. mydatasource2.tomcat.validationQuery = PILIH 1 Atau ada hal lain untuk diikuti ??
Nitish Kumar

2
Peringatan! Jika Anda mendefinisikan DataSource @Bean apa pun di aplikasi Anda, Spring Boot tidak akan mengonfigurasi kumpulan tersebut. docs.spring.io/spring-boot/docs/1.5.16.RELEASE/reference/… If you define your own DataSource bean, auto-configuration will not occur. Saya mengikuti panduan untuk OAuth2 dan telah @Bean(name = "OAuth") public DataSource secondaryDataSource()...serta tidak dikonfigurasi otomatis maupun digunakan testOnBorrow.
Chloe

28

Saran di atas tidak berhasil untuk saya. Apa yang benar-benar berhasil adalah penyertaan baris berikut di application.properties

spring.datasource.testWhileIdle = true
spring.datasource.timeBetweenEvictionRunsMillis = 3600000
spring.datasource.validationQuery = SELECT 1

Anda bisa menemukan penjelasannya di sini


5
Tautan yang Anda tambahkan mengatakan Jika koneksi database tidak aktif selama lebih dari 8 jam maka secara otomatis ditutup dan kesalahan di atas akan terjadi. Jadi, solusi Anda adalah tidak membiarkan koneksi tetap tidak aktif untuk jangka waktu yang lebih lama. Apakah ada cara agar saya dapat terhubung ke server SQL setelah dimulai ulang?
Akeshwar Jha

9

Pengaturan spring.datasource.tomcat.testOnBorrow=true di application.properties tidak berfungsi.

Pengaturan secara terprogram seperti di bawah ini berfungsi tanpa masalah.

import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;    

@Bean
public DataSource dataSource() {
    PoolProperties poolProperties = new PoolProperties();
    poolProperties.setUrl(this.properties.getDatabase().getUrl());         
    poolProperties.setUsername(this.properties.getDatabase().getUsername());            
    poolProperties.setPassword(this.properties.getDatabase().getPassword());

    //here it is
    poolProperties.setTestOnBorrow(true);
    poolProperties.setValidationQuery("SELECT 1");

    return new DataSource(poolProperties);
}

1
Jika Anda mendeklarasikan sumber data khusus, itu mungkin karena Anda mencoba menggunakan .tomcat default pegas. Jadi, jika Anda membuat kacang Sumber Data kustom lalu tambahkan @ConfigurationProperties (prefix = "spring.datasource.tomcat") ke kacang DataSource, lalu Anda dapat menyetelnya di properti aplikasi. Contoh Saya .. @Bean (name = "managementDataSource") @ConfigurationProperties (prefix = "management.datasource") public DataSource dataSource () {return DataSourceBuilder.create (). Build (); } management.datasource.test-on-borrow = true
Justin

8

Saya baru saja pindah ke Spring Boot 1.4 dan menemukan properti ini diganti namanya:

spring.datasource.dbcp.test-while-idle=true
spring.datasource.dbcp.time-between-eviction-runs-millis=3600000
spring.datasource.dbcp.validation-query=SELECT 1

2
Namanya setara. Lihat bagian penamaan properti di dokumen Spring Boot .
Stephen Harrison

@StephenHarrison: perhatikan awalan dbcp. * Ditambahkan di 1.4, pengikatan santai tidak berlaku dalam kasus ini.
YM

1
@Pawel: tergantung pada implementasi penggabungan mana yang tersedia dalam proyek Anda, itu mungkin bukan properti dbcp. * Untuk Anda, lihat Spring boot dengan SQL dan properti Sumber Data yang
YM

4

jawaban whoami adalah yang benar. Menggunakan properti seperti yang disarankan saya tidak dapat membuat ini berfungsi (menggunakan Spring Boot 1.5.3.RELEASE)

Saya menambahkan jawaban saya karena ini adalah kelas konfigurasi lengkap sehingga dapat membantu seseorang menggunakan Spring Boot:

@Configuration
@Log4j
public class SwatDataBaseConfig {

    @Value("${swat.decrypt.location}")
    private String fileLocation;

    @Value("${swat.datasource.url}")
    private String dbURL;

    @Value("${swat.datasource.driver-class-name}")
    private String driverName;

    @Value("${swat.datasource.username}")
    private String userName;

    @Value("${swat.datasource.password}")
    private String hashedPassword;

    @Bean
    public DataSource primaryDataSource() {
        PoolProperties poolProperties = new PoolProperties();
        poolProperties.setUrl(dbURL);
        poolProperties.setUsername(userName);
        poolProperties.setPassword(password);
        poolProperties.setDriverClassName(driverName);
        poolProperties.setTestOnBorrow(true);
        poolProperties.setValidationQuery("SELECT 1");
        poolProperties.setValidationInterval(0);
        DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
        return ds;
    }
}

Tahukah Anda mengapa kode khusus ini diperlukan dan mengapa Spring tidak hanya membaca properti ini dari file properti? Saya memiliki beberapa properti sumber data di file saya dan membaca semua properti lainnya tanpa masalah.
Paman Rambut Panjang

3

Saya memiliki masalah serupa. Spring 4 dan Tomcat 8. Saya memecahkan masalah dengan konfigurasi Spring

<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
    <property name="initialSize" value="10" />
    <property name="maxActive" value="25" />
    <property name="maxIdle" value="20" />
    <property name="minIdle" value="10" />
     ...
    <property name="testOnBorrow" value="true" />
    <property name="validationQuery" value="SELECT 1" />
 </bean>

Saya telah menguji. Ini bekerja dengan baik! Dua baris ini melakukan segalanya untuk terhubung kembali ke database:

<property name="testOnBorrow" value="true" />
<property name="validationQuery" value="SELECT 1" />

3

Jika ada yang menggunakan Sumber Data khusus

@Bean(name = "managementDataSource")
@ConfigurationProperties(prefix = "management.datasource")
public DataSource dataSource() {
    return DataSourceBuilder.create().build();
}

Properti akan terlihat seperti berikut. Perhatikan @ConfigurationProperties dengan awalan. Awalan adalah segalanya sebelum nama properti sebenarnya

management.datasource.test-on-borrow=true
management.datasource.validation-query=SELECT 1

Referensi untuk Versi Musim Semi 1.4.4.RELEASE


2

Seperti yang telah ditunjukkan oleh beberapa orang, spring-boot 1.4+, memiliki ruang nama khusus untuk empat kumpulan koneksi. Secara default, hikaricp digunakan di spring-boot 2+. Jadi, Anda harus menentukan SQL di sini. Standarnya adalah SELECT 1. Inilah yang Anda perlukan untuk DB2 misalnya: spring.datasource.hikari.connection-test-query=SELECT current date FROM sysibm.sysdummy1

Peringatan : Jika driver Anda mendukung JDBC4, kami sangat menyarankan untuk tidak menyetel properti ini. Ini untuk driver "warisan" yang tidak mendukung API JDBC4 Connection.isValid (). Ini adalah kueri yang akan dieksekusi sebelum koneksi diberikan kepada Anda dari pool untuk memvalidasi bahwa koneksi ke database masih hidup. Sekali lagi, coba jalankan pool tanpa properti ini, HikariCP akan mencatat kesalahan jika driver Anda tidak sesuai dengan JDBC4 untuk memberi tahu Anda. Default: tidak ada


0

Bagi mereka yang ingin melakukannya dari YAML dengan berbagai sumber data, ada posting blog yang bagus tentangnya: https://springframework.guru/how-to-configure-multiple-data-sources-in-a-spring-boot -aplikasi/

Pada dasarnya disebutkan bahwa Anda berdua perlu mengonfigurasi properti sumber data dan sumber data seperti ini:

@Bean
@Primary
@ConfigurationProperties("app.datasource.member")
public DataSourceProperties memberDataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@Primary
@ConfigurationProperties("app.datasource.member.hikari")
public DataSource memberDataSource() {
    return memberDataSourceProperties().initializeDataSourceBuilder()
            .type(HikariDataSource.class).build();
}

Jangan lupa untuk menghapus @Primarydari sumber data lain.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.