Spring 更改数据源连接url运行时
我正在从事一个使用spring+hibernate+mysql和c3p0进行连接池的项目 当前,连接池的属性是通过在src外部定义的属性加载的。(例如:${db_uname}) 当我们创建SpringBean时,一切都很好 由于某种原因,我们所连接的数据库可能无法访问,因此我们希望切换主机 需要实现回调,即连接到新主机并重新初始化池 任何关于如何优雅地覆盖现有数据源/连接池的指针都会大有帮助 下面是我的spring配置文件的样子Spring 更改数据源连接url运行时,spring,hibernate,datasource,connection-pooling,Spring,Hibernate,Datasource,Connection Pooling,我正在从事一个使用spring+hibernate+mysql和c3p0进行连接池的项目 当前,连接池的属性是通过在src外部定义的属性加载的。(例如:${db_uname}) 当我们创建SpringBean时,一切都很好 由于某种原因,我们所连接的数据库可能无法访问,因此我们希望切换主机 需要实现回调,即连接到新主机并重新初始化池 任何关于如何优雅地覆盖现有数据源/连接池的指针都会大有帮助 下面是我的spring配置文件的样子 <?xml version="1.0" encoding="
<?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&useUnicode=true&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" />
真的
org.hibernate.dialogue.mysqldialogue
${hibernate.cache.use\u query\u cache}
${hibernate.cache.use_second_level_cache}
org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
hibernate.cfg.xml
真的
com.mysql.jdbc.Driver
jdbc:mysql://${dbhost}/${dbschema}?zeroDateTimeBehavior=convertToNull&;useUnicode=true&;characterEncoding=UTF-8
${dbuser}
${dbpass}
org.hibernate.connection.C3P0ConnectionProvider
${hibernate.c3p0.maxSize}
${hibernate.c3p0.minSize}
${hibernate.c3p0.acquireIncrement}
${hibernate.c3p0.idleTestPeriod}
${hibernate.c3p0.maxStatements}
${hibernate.c3p0.timeout}
假设数据库模式是正确的,假设我在事件中获得了数据库凭据和主机信息,我需要“重新设置”连接池。如果您要求多个数据库连接。.在hibernate中,可以通过创建多个
hibernate.cfg.file
,这是不合适的
通过遵循这条路线,你可以做到这一点
SessionFactory sf = new Configuration().configure("somename.cfg.xml").buildSessionFactory();
当您的主连接未建立时,您已加载另一个休眠配置
…否则将不可能。是一个不错的选择
Xml或注释的用法如下:
<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>
cfg.xml不是hibernate.ejb.cfgfile的配置文件吗?它只定义了二级缓存配置?抽象路由数据源将帮助我路由到一个现有的数据源。我们的要求是从现在开始使用不同的数据源,它应该在发生事件时创建。我添加了spring配置文件作为questionRoutingDataSource的一部分,可以动态修改数据源映射。检查AbstractRoutingDataSource API。这太棒了!谢谢。
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);
}
}
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>
@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;
}