Java 未注入Spring RoutingDataSource validationQuery

Java 未注入Spring RoutingDataSource validationQuery,java,spring,datasource,configurationproperty,Java,Spring,Datasource,Configurationproperty,我使用RoutingDataSource为应用程序的每个租户动态创建数据源。8-12小时后,应用程序与数据库失去连接,我得到jpa事务异常。我发现以下属性负责验证和维持数据库连接,所以我将它们放在application.properties中 spring.datasource.initialize=false spring.datasource.test-while-idle=true spring.datasource.test-on-borrow=true spring.datasourc

我使用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
数据源bean是在以下类中创建的。如何将上述属性注入每个目标数据源

...

@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);
    }
}
。。。
@配置
公共类路由数据源配置{
公共静态最终字符串DEFAULT\u TENANT\u NAME=“DEFAULT\u TENANT”;
@自动连线
专用路由数据源属性路由属性;
/**
*定义应用程序的数据源
*
*@返回
*/
@豆子
@ConfigurationProperties(前缀=“spring.datasource”)
公共数据源数据源(){
Map dataSources=newhashmap();
对于(Map.Entry:routingProperties.getDataSources().entrySet()){
DataSourceProperties DataSourceProperties=entry.getValue();
put(entry.getKey(),createDataSource(dataSourceProperties));
}
RoutingDataSource dataSource=新建RoutingDataSource();
dataSource.setLenientFallback(false);
setDefaultTargetDataSource(createDefaultDataSource());
dataSource.setTargetDataSources(数据源);
dataSource.AfterPropertieSet();
返回数据源;
}
专用数据源createDataSource(数据源属性数据源属性){
DataSourceBuilder DataSourceBuilder=新的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());
}
返回dataSourceBuilder.build();
}
私有数据源createDefaultDataSource(){
Map dataSources=routingProperties.getDataSources();
如果(!dataSources.containsKey(默认租户名称)){
抛出新的BeanCreationException(String.format(
“未找到默认租户“%s”的配置,默认租户(名称));
}
DataSourceProperties DataSourceProperties=dataSources.get(默认租户名称);
返回createDataSource(dataSourceProperties);
}
}

我需要手动设置验证查询查询,以便根据实际情况创建数据源(在我的情况下是多个数据源)。 我知道Springboot 1.4+已经设置了属性,但这不是您遇到的问题

这有点难看,但对我来说很管用。它假设您使用的是Tomcat JDBC池(使用spring boot starter web时默认):


这帮我解决了一个我们曾经处理过的问题。奇怪的是,SpringBoot默认情况下不会从池中获取SQL连接,每次DB连接断开时,我们在PCF上运行的应用程序都会停止连接SQL DB。我们的DataSource对象是javax.sql.DataSource,调用setTypeSpecificProperties方法实现了这一点。
@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);
}