Рекомендации по использованию пула соединений Spring JDBC
У меня есть базовое Spring JDBC-приложение с довольно базовой конфигурацией:
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@1.1.1.1:1521:XXX"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</bean>
<bean id="dbThing" class="com.DbThing">
<property name="dataSource" ref="myDataSource"/>
</bean>
Я хотел бы представить пул соединений, и после прочтения нескольких потоков здесь, в SO, я немного запутался, какую библиотеку пулов использовать.
Библиотеки, которые, кажется, имеют больше кредитов на SO - это CP30 и DBCP. Поскольку я использую Oracle, я также мог бы использовать объединенный источник данных, предлагаемый драйвером. Я понимаю, что доступно больше библиотек - например, новые библиотеки пула Apache Tomcat 7.
Есть ли какая-то библиотека, которую мне действительно следует избегать?
Есть ли рекомендуемая конфигурация, которую я должен использовать с данной библиотекой?
Любую "военную историю" вы хотите поделиться?
4 ответа
Развитие C3PO и DBCP застопорилось в основном из-за зрелости. Я видел, как оба эти драйвера могут поддерживать сотни транзакций в секунду.
Пул Tomcat - это переработанный и обновленный драйвер DBCP. MyBatis 3.0 также содержит собственную реализацию пула, которая на основе проверки кода кажется надежной. Наконец, есть BoneCP, который претендует на лучшую производительность. Я еще не использовал ни одного из них в проекте.
Наверное, лучший совет - выбрать любого из них и проверить его. Весна облегчает замену позже.
В качестве альтернативы BoneCP, возможно, вы пробовали собственный пул соединений с базами данных Oracle?
У меня был хороший опыт за последние пару недель, так что, возможно, стоит попробовать - также, я полагаю, Oracle узнает кое-что о создании пула соединений, особенно в паре с собственной базой данных.
<bean id="dataSource" class="oracle.jdbc.pool.OracleConnectionPoolDataSource">
<property name="URL" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
ОБНОВЛЕНИЕ: Кроме того, если вы используете (один из) последние драйверы Oracle JDBC (11.2.0.1+), вы можете попробовать новый универсальный пул соединений. OracleConnectionPoolDataSource
кажется, официально объявлен устаревшим в пользу этого пула. Однако некоторые пользователи сообщают об ошибках, используя его, так что это может быть слишком рано. Я в состоянии использовать последние драйверы JDBC от Oracle, поэтому я попытаюсь обновить их здесь, как только у меня появится какая-либо информация по этому вопросу.
Дополнительная информация по этой теме: Oracle UCP
BoneCP
претендует, но затем вводится новый инструмент с именем HiKariCP
он преодолел многие недостатки, которые присутствовали в инструментах прохода, вы можете настроить его, изменив ниже application-context.xml
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="maximumPoolSize" value="10" />
<property name="minimumPoolSize" value="2" />
<property name="dataSourceClassName"
value="oracle.jdbc.pool.OracleDataSource" />
<property name="dataSourceProperties" ref="props" />
<property name="poolName" value="springHikariCP" />
</bean>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<constructor-arg ref="hikariConfig" />
</bean>
<util:properties id="props" location="classpath:datasource.properties"/>
в которой database.properties
Вы должны предоставить подробную информацию о базе данных, как показано ниже
url=jdbc:oracle:thin:@IP:port:SID/Databasename
user=usernmae
password=password
Для правильной демонстрации вы можете использовать эту ссылку
Определенно вы можете использовать C3P0, это разработано для корпоративного решения. Чтобы проверить преимущества вы можете следовать этому ответу.
Вот пример кода интеграции:
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager =
new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
Этот боб для получения JpaTransactionManager
,
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setPackagesToScan("YOUR.DATABSE.ENTITY.PACKAGE");
entityManagerFactoryBean.setJpaProperties(hibProperties());
return entityManagerFactoryBean;
}
Этот боб для получения LocalContainerEntityManagerFactoryBean
, Занимает DataSource
, PersistenceProviderClass
, Имя пакета сущностей PackagesToScan
и JpaProperties от hibProperties()
,
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
return properties;
}
Вот, env value are comming from application.properties
,
Проверьте следующие свойства:
hibernate.dialect: org.hibernate.dialect.Oracle12cDialect
hibernate.show_sql: false
hibernate.hbm2ddl.auto: none
Основная часть - настройка источника данных. Это дано ниже:
@Bean
public ComboPooledDataSource dataSource(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass(env.getProperty("db.driver"));
dataSource.setJdbcUrl(env.getProperty("db.url"));
dataSource.setUser(env.getProperty("db.username"));
dataSource.setPassword(env.getProperty("db.password"));
dataSource.setMinPoolSize(Integer.parseInt(env.getProperty("minPoolSize")));
dataSource.setMaxPoolSize(Integer.parseInt(env.getProperty("maxPoolSize")));
dataSource.setMaxIdleTime(Integer.parseInt(env.getProperty("maxIdleTime")));
dataSource.setMaxStatements(Integer.parseInt(env.getProperty("maxStatements")));
dataSource.setMaxStatementsPerConnection(Integer.parseInt(env.getProperty("maxStatementsPerConnection")));
dataSource.setMaxIdleTimeExcessConnections(10000);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
Он использует ComboPooledDataSource
это принимает много более важных параметров, таких как maxPoolSize,MinPoolSize, MaxIdleSize и т. д. Его параметры среды приведены ниже:
db.driver: oracle.jdbc.driver.OracleDriver // for Oracle
db.username: YOUR_USER_NAME
db.password: YOUR_USER_PASSWORD
db.url: DATABASE_URL
minPoolSize:5 // number of minimum poolSize
maxPoolSize:100 // number of maximum poolSize
maxIdleTime:5 // In seconds. After that time it will realease the unused connection.
maxStatements:1000
maxStatementsPerConnection:100
maxIdleTimeExcessConnections:10000
Вот полный рабочий пример кода:
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.util.Properties;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories
@PropertySource("classpath:application.properties")
@Scope("singleton")
public class TestDataSource {
@Autowired
private Environment env;
@Qualifier("dataSource")
@Autowired
private DataSource dataSource;
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager =
new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setPackagesToScan("YOUR.PACKAGE.NAME");
entityManagerFactoryBean.setJpaProperties(hibProperties());
return entityManagerFactoryBean;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
@Bean
public ComboPooledDataSource dataSource(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass(env.getProperty("db.driver"));
dataSource.setJdbcUrl(env.getProperty("db.url"));
dataSource.setUser(env.getProperty("db.username"));
dataSource.setPassword(env.getProperty("db.password"));
dataSource.setMinPoolSize(Integer.parseInt(env.getProperty("minPoolSize")));
dataSource.setMaxPoolSize(Integer.parseInt(env.getProperty("maxPoolSize")));
dataSource.setMaxIdleTime(Integer.parseInt(env.getProperty("maxIdleTime")));
dataSource.setMaxStatements(Integer.parseInt(env.getProperty("maxStatements")));
dataSource.setMaxStatementsPerConnection(Integer.parseInt(env.getProperty("maxStatementsPerConnection")));
dataSource.setMaxIdleTimeExcessConnections(10000);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
return properties;
}
}
Другие вещи. Вот ссылка Gradle
compile group: 'org.hibernate', name: 'hibernate-c3p0', version: '5.2.10.Final'
Надеюсь, что это поможет вам. Спасибо:)