example spring hibernate datasource connection-pooling

spring - example - Cambiar el tiempo de ejecución de url de conexión del origen de datos



spring hibernate mysql (3)

Si está solicitando conexiones de bases de datos múltiples, es posible con hibernación creando múltiples archivos hibernate.cfg.file , que es un poco inapropiado

Al seguir la línea, puedes lograr eso.

SessionFactory sf = new Configuration().configure("somename.cfg.xml").buildSessionFactory();

Cuando su conexión principal no está establecida, tiene que cargar otra hibernate configuration ... de lo contrario no será posible.

Estoy trabajando en un proyecto que usa spring + hibernate + mysql y c3p0 para la agrupación de conexiones.

Actualmente las propiedades para el grupo de conexiones se cargan a través de propiedades definidas fuera del src. (por ejemplo: $ {db_uname})

Todo comienza bien cuando creamos el Spring Bean.

Puede suceder que la base de datos a la que nos hemos conectado sea inaccesible por algún motivo, y nos gustaría cambiar los hosts.

Necesita implementar una devolución de llamada, donde se supone que debe conectarse al nuevo host y reiniciar el grupo

Cualquier sugerencia sobre cómo anular correctamente la fuente de datos existente / grupo de conexiones sería de gran ayuda.

Así es como se ve mi archivo de configuración de primavera

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"> <!-- Component scans --> <import resource="component-scans-1.xml" /> <import resource="component-scans-2.xml" /> <util:properties id="serviceManagerProperties" location="classpath:servicemanagers.properties" /> <!-- Properties file --> <context:property-placeholder location="classpath:database.config.properties,classpath:framework.properties" /> <!-- context:annotation-config / --> <tx:annotation-driven transaction-manager="transactionManager" /> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <context:mbean-server id="mbeanServer" /> <context:mbean-export server="mbeanServer" default-domain="a.b.c" /> <bean id="cacheManager" factory-method="getInstance" class="net.sf.ehcache.CacheManager" /> <bean class="net.sf.ehcache.management.ManagementService" init-method="init"> <constructor-arg ref="cacheManager" /> <constructor-arg ref="mbeanServer" /> <constructor-arg value="false" /> <constructor-arg value="false" /> <constructor-arg value="false" /> <constructor-arg value="true" /> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="jpaVendorAdapter" ref="jpaAdapter" /> <property name="persistenceXmlLocation" value="classpath*:META-INF/framework-persistence.xml" /> <property name="persistenceUnitName" value="PU-NAME" /> <property name="jpaProperties"> <props> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop> <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop> <prop key="hibernate.cache.region.factory_class"> org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory </prop> <prop key="hibernate.ejb.cfgfile">hibernate.cfg.xml</prop> <prop key="hibernate.generate_statistics">true</prop> <!-- CONNECTION SETTINGS --> <prop key="hibernate.connection.driver_class"> com.mysql.jdbc.Driver </prop> <prop key="hibernate.connection.url"> jdbc:mysql://${dbhost}/${dbschema}?zeroDateTimeBehavior=convertToNull&amp;useUnicode=true&amp;characterEncoding=UTF-8 </prop> <prop key="hibernate.connection.username">${dbuser}</prop> <prop key="hibernate.connection.password">${dbpass}</prop> <!-- CONNECTION POOLING --> <prop key="hibernate.connection.provider_class"> org.hibernate.connection.C3P0ConnectionProvider </prop> <prop key="hibernate.c3p0.maxPoolSize">${hibernate.c3p0.maxSize}</prop> <prop key="hibernate.c3p0.minPoolSize">${hibernate.c3p0.minSize}</prop> <prop key="hibernate.c3p0.acquireIncrement">${hibernate.c3p0.acquireIncrement}</prop> <prop key="hibernate.c3p0.idleConnectionTestPeriod">${hibernate.c3p0.idleTestPeriod}</prop> <prop key="hibernate.c3p0.maxStatements">${hibernate.c3p0.maxStatements}</prop> <prop key="hibernate.c3p0.timeout">${hibernate.c3p0.timeout}</prop> </props> </property> </bean> <bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />

Suponiendo que el esquema de la base de datos es correcto, digamos que obtengo las credenciales de la base de datos y la información del host en el evento, necesito ''volver a establecer'' el grupo de conexiones.


AbstractRoutingDataSource es una buena opción.

Xml o anotación usada así:

<bean id="ds1" class="..c3p0.DataSource"> ... </bean> <bean id="ds2" class="..c3p0.DataSource"> ... </bean> <bean id="dataSource" class="..xxx.RoutingDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="ds1" value-ref="ds1"/> <entry key="ds2" value-ref="ds2"/> </map> </property> <property name="defaultTargetDataSource" ref="ds1"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> ... </bean>

Luego crea una clase para determinar el datasoruce actual.

public class RoutingDataSource extends AbstractRoutingDataSource { private static final ThreadLocal<String> holder = new ThreadLocal<String>(); protected Object determineCurrentLookupKey() { return holder.get(); } public static void clear(){ holder.remove(); } public static void setDataSourceKey(String key){ holder.set(key); } }

Por cierto, ¡la declaración de "probar-finalmente" es aburrida!

try{ RoutingDataSource.setDataSourceKey("ds1"); myDao.doXXX(); }finally{ RoutingDataSource.clear(); }


<beans:bean id="dataSource" class="org.springframework.aop.framework.ProxyFactoryBean"> <beans:property name="targetSource" ref="swappableDataSource" /> </beans:bean> <beans:bean id="dummyDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" /> <beans:bean name="swappableDataSource" class="org.springframework.aop.target.HotSwappableTargetSource"> <beans:constructor-arg ref="dummyDataSource" /> </beans:bean>

y en algún lugar de tu código puedes hacer esto.

@Autowired HotSwappableTargetSource swapable; public void changeDatasource() throws Exception { swapable.swap(createNewSource(); } ComboPooledDataSource createNewSource() throws Exception { ComboPooledDataSource ds2 = new ComboPooledDataSource(); ds2.setJdbcUrl(url); ds2.setDriverClass(driver); ds2.setUser(username); ds2.setPassword(password); return ds2; }