gpt4 book ai didi

spring - 更改数据源连接 url 运行时

转载 作者:行者123 更新时间:2023-12-04 15:24:26 24 4
gpt4 key购买 nike

我正在开发一个使用 spring + hibernate + mysql 和 c3p0 进行连接池的项目。

目前,连接池的属性是通过在 src 之外定义的属性加载的。 (例如:${db_uname})

当我们创建 spring bean 时,一切都很好。

可能会发生我们连接的数据库由于某种原因无法访问,并且我们想切换主机。

需要实现回调,在那里它应该连接到新主机并重新初始化池

关于如何优雅地覆盖现有数据源/连接池的任何指示都会有很大帮助。

这是我的 spring 配置文件的样子

<?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" />

假设数据库模式是正确的,假设我在事件中获得了数据库凭据和主机信息,我需要“重新设置”连接池。

最佳答案

AbstractRoutingDataSource是个不错的选择。

像这样使用的 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>

然后构建一个类来确定当前的数据源。
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-finally' 语句很无聊!
try{
RoutingDataSource.setDataSourceKey("ds1");
myDao.doXXX();
}finally{
RoutingDataSource.clear();
}

关于spring - 更改数据源连接 url 运行时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14555611/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com