Я реализовал мультитенантную архитектуру и ввел пул соединений C3P0
.
С помощью графического интерфейса пользователя я пытаюсь запросить свое приложение с помощью простой формы поиска.Эта форма имеет кнопку для вызова внутреннего метода для извлечения моего результата.
Если я несколько раз нажму на мой запрос, у меня будет зависание приложения из-за исчерпания пула соединений 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();
}
Файл моей базы данных.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