2

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);
    }
}
4

1 に答える 1

2

77.2 (および私の場合は複数のデータソース)に従って実用的にデータソースを作成するときに、validation-query クエリを手動で設定する必要がありました。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);
}
于 2017-03-10T07:44:54.743 に答える