Spring RoutingDataSource validationQuery не внедряется

Я использую RoutingDataSource для динамического создания источников данных для каждого владельца нашего приложения. После 8 - 12 часов приложение теряет связь с базой данных, и я получаю исключение транзакции jpa. Я обнаружил, что следующие свойства отвечают за проверку и поддержание соединения с базой данных, поэтому я поместил их в мои application.properties.

spring.datasource.initialize=false
spring.datasource.test-while-idle=true
spring.datasource.test-on-borrow=true
spring.datasource.validation-query=SELECT 1

Компонент источника данных создается в следующем классе. Как внедрить вышеуказанные свойства в каждый целевой источник данных?

...

@Configuration
public class RoutingDataSourceConfiguration {

    public static final String DEFAULT_TENANT_NAME = "default_tenant";

    @Autowired
    private RoutingDataSourceProperties routingProperties;

    /**
     * Defines the data source for the application
     *
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        Map<Object, Object> dataSources = new HashMap<>();
        for (Map.Entry<String, DataSourceProperties> entry : routingProperties.getDataSources().entrySet()) {
            DataSourceProperties dataSourceProperties = entry.getValue();
            dataSources.put(entry.getKey(), createDataSource(dataSourceProperties));
        }
        RoutingDataSource dataSource = new RoutingDataSource();
        dataSource.setLenientFallback(false);
        dataSource.setDefaultTargetDataSource(createDefaultDataSource());
        dataSource.setTargetDataSources(dataSources);
        dataSource.afterPropertiesSet();
        return dataSource;
    }

    private DataSource createDataSource(DataSourceProperties dataSourceProperties) {
        DataSourceBuilder dataSourceBuilder = new DataSourceBuilder(this.getClass().getClassLoader());
        dataSourceBuilder.driverClassName(dataSourceProperties.getDriverClassName())
                .url(dataSourceProperties.getUrl())
                .username(dataSourceProperties.getUsername())
                .password(dataSourceProperties.getPassword());

        if (dataSourceProperties.getType() != null) {
            dataSourceBuilder.type(dataSourceProperties.getType());
        }
        return dataSourceBuilder.build();
    }

    private DataSource createDefaultDataSource() {
        Map<String, DataSourceProperties> dataSources = routingProperties.getDataSources();
        if (!dataSources.containsKey(DEFAULT_TENANT_NAME)) {
            throw new BeanCreationException(String.format(
                    "No configuration for default tenant '%s' found", DEFAULT_TENANT_NAME));
        }
        DataSourceProperties dataSourceProperties = dataSources.get(DEFAULT_TENANT_NAME);
        return createDataSource(dataSourceProperties);
    }
}

1 ответ

Мне нужно было установить запрос запроса валидации вручную при прагматическом создании источника данных в соответствии с 77.2 (и в моем случае несколько источников данных). Я знаю, что Springboot 1.4+ изменил набор свойств, но проблема не в этом.

Это немного некрасиво, но у меня это сработало. Предполагается, что вы используете пул Tomcat JDBC (по умолчанию при использовании spring-boot-starter-web):

@Value("${spring.datasource.validation-query}")
private String validationQuery;

@Bean
@ConfigurationProperties("spring.datasource")
@Primary
  public DataSourceProperties ftmDataSourceProperties() {
  return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("spring.datasource")
@Primary
public DataSource ftmDataSource() {
  DataSource ds = ftmDataSourceProperties().initializeDataSourceBuilder().build();
  setTypeSpecificProperties(validationQuery,ds);
  return ds;
}

private void setTypeSpecificProperties(String validationQuery, DataSource dataSource) {
  org.apache.tomcat.jdbc.pool.DataSource typedDS = (org.apache.tomcat.jdbc.pool.DataSource) dataSource;
  typedDS.setValidationQuery(validationQuery);
  typedDS.setTestOnBorrow(true);
  typedDS.setLogValidationErrors(true);
}
Другие вопросы по тегам