multi-tenant - 调用一些 @Transactional 方法后 C3P0 耗尽
问题描述
我已经实现了一个多租户架构,并引入了一个C3P0
连接池。
通过 GUI,我尝试使用简单的搜索表单查询我的应用程序。这个表单有一个按钮来调用后端方法来提取我的结果。
如果我多次单击搜索,我的应用程序将冻结,因为 C3P0 连接池已用尽。
因为C3P0
增量连接使用acquireIncrement
参数管理,但是当它到达时MAX_SIZE
崩溃
所以我的情况如下:
我有一个注释为的类@Service
和一个注释为@Transactional
执行查询的方法,如下所示:
@Override
@Transactional
public String findPatientCountDao(Paziente paziente,
boolean searchForAllPatients, boolean enabledDemetra) {
String querySqlOrHql = this.createQuery(paziente, searchForAllPatients, true, 0, 0);
Query q = getSession().createQuery(querySqlOrHql);
List<Object[]> obj = q.list();
return "" + obj.get(0);
}
我的 Hibernate 配置由 HibernateConf 类管理,如下所示:
@Configuration
@EnableTransactionManagement
public class HibernateConf {
@Autowired
DataSourceBasedMultiTenantConnectionProviderImpl dataSources;
@Autowired
TenantSchemaResolver tenantSchemaResolver;
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
if (TenantContext.getCurrentTenant()==null)
TenantContext.setCurrentTenant("tenant_1");
sessionFactory.setDataSource(dataSources.selectDataSource(TenantContext.getCurrentTenant()));
sessionFactory.setPackagesToScan("it.spi");
org.hibernate.cfg.Configuration configuration = new org.hibernate.cfg.Configuration();
configuration.setProperties(hibernateProperties());
//sessionFactory.setHibernateProperties(hibernateProperties());
sessionFactory.setConfigLocation(new ClassPathResource("hibernate_ehr/hibernate.cfg.xml"));
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
System.out.println("Hibernate Java Config serviceRegistry created");
sessionFactory = (LocalSessionFactoryBean) configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
@Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager =
new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private final Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.put(Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
hibernateProperties.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, dataSources);
hibernateProperties.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantSchemaResolver);
hibernateProperties.put(Environment.USE_STREAMS_FOR_BINARY, true);
hibernateProperties.put(Environment.DIALECT, "org.hibernate.dialect.Oracle10gDialect");
hibernateProperties.put(Environment.DRIVER, "oracle.jdbc.OracleDriver");
hibernateProperties.put(Environment.SHOW_SQL, false);
hibernateProperties.put(Environment.FORMAT_SQL, false);
hibernateProperties.put(Environment.USE_SQL_COMMENTS, false);
hibernateProperties.put(Environment.C3P0_MIN_SIZE, 50); //Minimum size of pool
hibernateProperties.put(Environment.C3P0_MAX_SIZE, 100); //Maximum size of pool
hibernateProperties.put(Environment.C3P0_ACQUIRE_INCREMENT, 10);//Number of connections acquired at a time when pool is exhausted
hibernateProperties.put(Environment.C3P0_TIMEOUT, 1800); //Connection idle time
hibernateProperties.put(Environment.C3P0_MAX_STATEMENTS, 600); //PreparedStatement cache size
return hibernateProperties;
}
我的数据源配置:
@Primary
@Bean(name = { "dataSource", "dataSource1" })
@ConfigurationProperties(prefix = "spring.multitenancy.datasource1")
public DataSource dataSource1() {
DataSourceBuilder factory = DataSourceBuilder
.create(this.multitenancyProperties.getDatasource1().getClassLoader())
.driverClassName(this.multitenancyProperties.getDatasource1().getDriverClassName())
.username(this.multitenancyProperties.getDatasource1().getUsername())
.password(this.multitenancyProperties.getDatasource1().getPassword())
.url(this.multitenancyProperties.getDatasource1().getUrl()).type(ComboPooledDataSource.class);
return factory.build();
}
我的 database.properties 文件
spring.multitenancy.datasource.type = com.mchange.v2.c3p0.ComboPooledDataSource
spring.multitenancy.datasource.url=jdbc:oracle:thin:@xx.xx.xx.xx:1521/xxx
spring.multitenancy.datasource.username=xxx
spring.multitenancy.datasource.password=yyy
spring.multitenancy.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.multitenancy.datasource.testWhileIdle = true
spring.multitenancy.datasource.validationQuery = SELECT 1
spring.multitenancy.datasource.hibernate.c3p0.max_size=100
spring.multitenancy.datasource.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
解决方案
推荐阅读
- php - PHP一次删除字符串中的某个字符串
- firebase - Nexmo:接收短信
- regex - 正则表达式:飞镖中的持续时间(小时,分钟)
- apache-kafka - kafka producer - 如何知道哪个密钥将进入哪个分区?
- amazon-web-services - bastion 如何知道要在 AWS 中连接到哪个 rds 实例
- django-rest-framework - Django REST:排除一些字段并过滤嵌套的序列化程序
- c++ - 类型的基于范围的“for”表达式......类型不完整
- javascript - mongoDB保存数据失败
- networking - 无法将 Route53 记录定向到新服务器
- python - 如何用字典调用文件并将其传递给类对象?