问题描述
我正在使用RoutingDataSource为我们的应用程序的每个租户动态创建数据源。 8到12个小时后,应用程序应用程序失去了与数据库的连接,并且我收到jpa事务异常。我发现以下属性负责验证和维持数据库连接,因此将它们放在了application.properties中。
I'm using RoutingDataSource to dynamically create datasources for each tenant of our application. After 8 - 12 hours application application losts connection with database and I'm getting jpa transaction exception. I found that the following properties are responsible for validation and sustaining database connection so I placed them in my 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是在以下类中创建的。如何将以上属性注入到每个目标数据源?
Data source bean is created in the following class. How to inject above properties to each target datasource?
...
@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);
}
}
推荐答案
I在根据(在我的情况下是多个数据源)。
我知道Springboot 1.4+具有属性集,但这不是您遇到的问题。
I needed to set validation-query query manually when creating a datasource pragmatically as per 77.2 (and in my case multiple datasources).I know Springboot 1.4+ has changed the properties set, but this is not the issue you are having.
这有点难看,但对我有用。假定您正在使用Tomcat JDBC池(使用spring-boot-starter-web时为默认设置):
It's a bit ugly, but it worked for me. It assumes you are using Tomcat JDBC pooling (default when using 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);
}
这篇关于Spring RoutingDataSourcevalidationQuery没有被注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!