2016-04-15 89 views
2

我正在使用RoutingDataSource爲我們的應用程序的每個租戶動態創建數據源。 8-12小時後,應用程序應用程序丟失與數據庫的連接,並且出現jpa事務異常。我發現以下屬性負責驗證和維持數據庫連接,所以我將它們放在我的application.properties中。Spring RoutingDataSource validationQuery未被注入

​​3210

數據源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); 
    } 
} 

回答

1

我需要集驗證查詢查詢手動創建數據源務實按照77.2(在我的情況下多個數據源)時。 我知道Springboot 1.4+有changed屬性設置,但這不是你遇到的問題。

這有點難看,但它對我有用。它假定您正在使用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); 
}