Spring Boot JPA - налаштування автоматичного підключення


107

У мене є приємний маленький веб-додаток Spring Boot JPA. Він розміщений на Amazon Beanstalk і використовує Amazon RDS для збереження даних. Однак він використовується не так часто, і через деякий час виходить з ладу за таким винятком:

com.mysql.jdbc.exceptions.jdbc4.CommunicationException: Останній пакет, успішно отриманий від сервера, був 79,870,633 мілісекунди тому.
Останній пакет, успішно відправлений на сервер, був 79 870 634 мілісекунди тому. довше, ніж налаштоване сервером значення 'wait_timeout'. Вам слід розглянути питання про те, чи закінчується термін дії та / або тестує термін дії з'єднання перед використанням у вашій програмі, збільшуючи налаштовані на сервері значення для таймаутів клієнта або використовуючи властивість з'єднання Connector / J 'autoReconnect = true', щоб уникнути цієї проблеми.

Я не впевнений, як налаштувати цей параметр, і не можу знайти інформацію про нього на http://spring.io (хоча дуже хороший сайт). Які є ідеї чи покажчики інформації?


Використовуйте це, щоб роздрукувати свої DataSourceта перевірити його властивості. stackoverflow.com/a/36586630/148844 Spring Boot не налаштовується автоматично, DataSourceякщо у вас є такі, @Beansякі визначають a DataSource. docs.spring.io/spring-boot/docs/1.5.16.RELEASE/reference/…
Хлоя

Відповіді:


141

Я припускаю, що завантаження налаштовує DataSourceдля вас. У цьому випадку, і оскільки ви використовуєте MySQL, ви можете додати наступне до своїх application.propertiesдо 1,3

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

Як було відзначено djxak в коментарях, 1.4+ визначає конкретні простору імена для чотирьох з'єднань басейнів Пружини завантаження підтримує: tomcat, hikari, dbcp, dbcp2( dbcpнебажано 1.5). Вам потрібно перевірити, який пул з'єднань ви використовуєте, і перевірити, чи підтримується ця функція. Наведений вище приклад був для tomcat, тому вам доведеться записати його наступним чином у версії 1.4+:

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

Слід зазначити , що використання autoReconnectє не рекомендується :

Використання цієї функції не рекомендується, оскільки вона має побічні ефекти, пов’язані зі станом сеансу та узгодженістю даних, коли програми не обробляють SQLExceptions належним чином, і призначена для використання лише тоді, коли ви не можете налаштувати додаток для обробки SQLExceptions в результаті мертві та несвіжі з'єднання належним чином.


8
це тому, що ми гармонізували спосіб запису ключів у документації. Ми завжди використовували розслаблене в’яжуче, так що і те, spring.datasource.testOnBorrowі spring.datasource.test-on-borrowбуде добре. Перегляньте документацію для отримання більш детальної інформації.
Стефан Ніколь

17
Оскільки це може заплутати інших: SELECT 1гарантує, що з'єднання було протестовано ще до того, як передано заявку. Використовуючи testOnBorrow = true, об'єкти будуть перевірені перед запозиченням у пулу. Якщо об’єкт не вдасться перевірити, він буде скинутий з пулу і спробує запозичити інший. ПРИМІТКА - щоб справжнє значення мало будь-який ефект, параметр validationQuery повинен бути встановлений на ненульовий рядок.
Рік

14
Увага! Навесні черевику 1.4+ це змінилося : там було визначено нові специфічні простору імен для чотирьох з'єднань басейнів пружинних опор: tomcat, hikari, dbcp, dbcp2. Так, наприклад, для tomcat-jdbcпулу з'єднань властивості повинні бути: spring.datasource.tomcat.testOnBorrow=trueі spring.datasource.tomcat.validationQuery=SELECT 1.
Руслан Стельмаченко

1
Якщо я сам налаштовую два різних джерела даних, то як мені надати ці конфігурації? Чи потрібно мені надати цю конфігурацію для обох джерел даних, таких як spring.datasource.mydatasource1.tomcat.testOnBorrow = справжній spring.datasource.mydatasource1.tomcat.validationQuery = SELECT 1 spring.datasource.mydatasource2.tomcat.testOnBorrow = справжній spring.datasource. mydatasource2.tomcat.validationQuery = ВИБІР 1 Або слід щось ще слідкувати ??
Нітіш Кумар

2
Увага! Якщо у вашому додатку визначено будь-який DataSource @Bean, тоді Spring Boot не налаштовує пул. docs.spring.io/spring-boot/docs/1.5.16.RELEASE/reference/… If you define your own DataSource bean, auto-configuration will not occur. Я слідував керівництвом по OAuth2 і мав, @Bean(name = "OAuth") public DataSource secondaryDataSource()...і він не був налаштований автоматично і не використовувався testOnBorrow.
Хлоя

28

Вищенаведені пропозиції для мене не спрацювали. Насправді працювало - включення наступних рядків у application.properties

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

Ви можете знайти пояснення тут


5
Посилання, яке ви додали, говорить про те, що якщо з'єднання з базою даних неактивне більше 8 годин, воно автоматично закривається, і сталася помилка, що була вище. Отже, ваше рішення - не дозволяти з'єднанню залишатися неактивним довше. Чи є спосіб я підключитися до сервера SQL після його перезавантаження?
Akeshwar Jha

9

Налаштування spring.datasource.tomcat.testOnBorrow=trueв application.properties не працювало.

Програмна настройка, як показано нижче, працювала без проблем.

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
Якщо ви декларуєте користувацький джерело даних, це може бути тому, що ви намагаєтесь використовувати .tomcat весни за замовчуванням. Отже, якщо ви створюєте користувацьку базу даних, тоді додайте @ConfigurationProperties (префікс = "spring.datasource.tomcat") в боб DataSource, і тоді він повинен дозволяти встановлювати їх у властивості програми. Мій приклад .. @Bean (name = "managementDataSource") @ConfigurationProperties (префікс = "management.datasource") публічний DataSource dataSource () {return DataSourceBuilder.create (). Build (); } management.datasource.test-on-заим = правда
Джастін

8

Щойно я перейшов до Spring Boot 1.4 і виявив, що ці властивості були перейменовані:

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

2
Назви рівноцінні. Дивіться розділ щодо назви властивостей у документах Spring Boot .
Стівен Гаррісон

@StephenHarrison: помітьте префікс dbcp. *, Доданий у 1.4, розслаблене прив’язка не застосовується в цьому випадку.
YM

1
@Pawel: залежно від того, яка реалізація об’єднання доступна у вашому проекті, це може бути не властивостями dbcp. * Для вас, див. Весільне завантаження з SQL та відповідні властивості Datasource
YM

4

відповідь whoami правильна. Використовуючи вказані властивості, я не зміг змусити це працювати (використовуючи Spring Boot 1.5.3.RELEASE)

Я додаю свою відповідь, оскільки це повний клас конфігурації, щоб це могло допомогти комусь, хто використовує 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;
    }
}

Чи знаєте ви, чому потрібен цей спеціальний код і чому Spring не просто прочитає ці властивості з файлу властивостей? У мене є кілька властивостей джерела даних у моєму файлі, і він читає всі інші без проблем.
Дядько Довге волосся

3

У мене є аналогічна проблема. Spring 4 і Tomcat 8. Я вирішую проблему з конфігурацією 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>

Я протестував. Це добре працює! Цей два рядки роблять все для того, щоб знову підключитися до бази даних:

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

3

У випадку, якщо хтось користується користувацьким DataSource

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

Властивості повинні виглядати наступним чином. Зверніть увагу на @ConfigurationProperties з префіксом. Префікс - це все перед фактичною назвою властивості

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

Посилання на версію Spring 1.4.4


2

Як вже зазначали деякі, Spring-boot 1.4+ має певні простори імен для чотирьох пулів підключень. За замовчуванням hikaricp використовується у весняному завантаженні 2+. Тому вам доведеться вказати тут SQL. Типовим є SELECT 1. Ось що вам знадобиться для DB2, наприклад: spring.datasource.hikari.connection-test-query=SELECT current date FROM sysibm.sysdummy1

Caveat : Якщо ваш драйвер підтримує JDBC4, ми настійно рекомендуємо не встановлювати цю властивість. Це для "застарілих" драйверів, які не підтримують API JDBC4 Connection.isValid (). Це запит, який буде виконаний перед тим, як вам буде надано з'єднання з пулу, щоб перевірити, що з'єднання з базою даних залишається живим. Знову ж таки, спробуйте запустити пул без цієї властивості, HikariCP зафіксує помилку, якщо ваш драйвер не відповідає JDBC4, щоб повідомити про це. За замовчуванням: немає


0

Для тих, хто хоче це зробити з YAML з кількома джерелами даних, є чудова публікація про це у блозі: https://springframework.guru/how-to-configure-multiple-data-sources-in-a-spring-boot -приклад /

По суті, це говорить про те, що вам потрібно налаштувати властивості джерела даних та джерело даних на зразок цього:

@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();
}

Не забудьте видалити @Primaryз інших джерел даних.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.