java - example - Prácticas recomendadas para el conjunto de conexiones de Spring JDBC
spring jdbc maven (4)
Como alternativa a BoneCP, ¿has probado el grupo de conexiones de la base de datos de Oracle?
He tenido buenas experiencias durante las últimas semanas, por lo que podría valer la pena intentarlo. Además, supongo que Oracle sabría una cosa o dos acerca de cómo hacer un pool de conexiones, especialmente cuando se combina con su propia base de datos.
<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>
ACTUALIZACIÓN : Además, si está utilizando (uno de) los últimos controladores Oracle JDBC (11.2.0.1+), es posible que desee probar el nuevo conjunto de conexiones universal. El OracleConnectionPoolDataSource
parece ser oficialmente obsoleto a favor de este grupo. Sin embargo, algunos usuarios han informado de errores al usarlo, por lo que puede ser demasiado pronto. Estoy en condiciones de usar los últimos controladores JDBC de Oracle, así que lo probaré y actualizaré aquí tan pronto como tenga información sobre esto.
Más información sobre este hilo SO: Oracle UCP
Tengo una aplicación Spring JDBC básica con una configuración bastante básica:
<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>
Me gustaría introducir un grupo de conexiones y después de leer varios hilos aquí en SO, estoy un poco confundido sobre qué biblioteca de agrupación usar.
Las bibliotecas que parecen tener más créditos en SO son CP30 y DBCP . Como utilizo Oracle, también podría usar la fuente de datos agrupados que ofrece el controlador. Entiendo que hay más bibliotecas disponibles, por ejemplo, las nuevas bibliotecas de agrupación de Apache Tomcat 7.
¿Hay alguna biblioteca que realmente deba evitar?
¿Hay alguna configuración recomendada que deba usar con una biblioteca determinada?
¿Alguna "historia de guerra" que te interese compartir?
Definitivamente puede usar C3P0, esto está desarrollado para soluciones empresariales. Para comprobar las ventajas puede seguir esta respuesta .
Aquí está el código de integración de ejemplo:
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager =
new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
Este Bean es para obtener 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;
}
Este Bean es para obtener LocalContainerEntityManagerFactoryBean
. Toma DataSource
, PersistenceProviderClass
, Entity Package Package PackagesToScan
y JpaProperties de 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;
}
Aquí, el env value are comming from application.properties
.
Compruebe las propiedades abajo:
hibernate.dialect: org.hibernate.dialect.Oracle12cDialect
hibernate.show_sql: false
hibernate.hbm2ddl.auto: none
La parte principal es la configuración de DataSource. Eso se da a continuación :
@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;
}
Está utilizando ComboPooledDataSource
que está tomando muchos parámetros más importantes como maxPoolSize, MinPoolSize, MaxIdleSize, etc. Su parámetro de entorno se da a continuación:
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
Aquí está el código de muestra de trabajo completo:
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;
}
}
Otras cosas. Aquí está el enlace de Gradle
compile group: ''org.hibernate'', name: ''hibernate-c3p0'', version: ''5.2.10.Final''
Espero que esto te ayudará. Gracias :)
El desarrollo de C3PO y DBCP se estancaron principalmente porque están maduros. He visto que estos dos controladores pueden admitir cientos de transacciones por segundo.
El grupo de Tomcat es un controlador DBCP revisado y actualizado. MyBatis 3.0 también contiene su propia implementación de agrupación que, en función de la inspección del código, parece sólida. Finalmente, hay BoneCP que dice tener el mejor rendimiento. No he usado ninguno de estos en un proyecto todavía.
Probablemente el mejor consejo es elegir cualquiera de ellos probarlo. Spring hace que sea más fácil cambiarlo más tarde.
BoneCP
ha estado reclamando pero luego se presenta una nueva herramienta llamada HiKariCP
que ha superado muchas desventajas que estaban presentes en las herramientas de pase. Puede configurarlo mediante el cambio a continuación en 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"/>
donde en database.properties
debe proporcionar detalles de la base de datos como a continuación
url=jdbc:oracle:thin:@IP:port:SID/Databasename
user=usernmae
password=password
Para una demostración adecuada, puedes usar este enlace