利用AbstractRoutingDataSource实现动态数据源切换 (Spring+Hibernate)

转载之:http://exceptioneye.iteye.com/blog/1698064


Spring配置多数据源的方式和具体使用过程


1、数据源的名称常量类

    public enum DynamicDataSourceGlobal {

Java代码   收藏代码
  1.     ORCL,   
  2.     ISC  
  3. }  
 

2、建立一个获得和设置上下文环境的类,主要负责改变上下文数据源的名称

    public class DynamicDataSourceHolder {

Java代码   收藏代码
  1. // 线程本地环境  
  2. private static final ThreadLocal<DynamicDataSourceGlobal> contextHolder = new ThreadLocal<DynamicDataSourceGlobal>();  
  3.   
  4. // 设置数据源类型  
  5. public static void setDataSourceType(DynamicDataSourceGlobal dataSourceType) {  
  6.     Assert.notNull(dataSourceType, "DataSourceType cannot be null");  
  7.     contextHolder.set(dataSourceType);  
  8. }  
  9.   
  10. // 获取数据源类型  
  11. public static DynamicDataSourceGlobal getDataSourceType() {  
  12.     return (DynamicDataSourceGlobal) contextHolder.get();  
  13. }  
  14.   
  15. // 清除数据源类型  
  16. public static void clearDataSourceType() {  
  17.     contextHolder.remove();  
  18. }  
 

3、建立动态数据源类,注意,这个类必须继承AbstractRoutingDataSource,且实现方法 determineCurrentLookupKey,该方法返回一个Object,一般是返回字符串

    public class DynamicDataSource extends AbstractRoutingDataSource {

Java代码   收藏代码
  1.     @Override  
  2.     protected Object determineCurrentLookupKey() {  
  3.         return DynamicDataSourceHolder.getDataSourceType();  
  4.     }  
  5.   
  6. }  

4、编写spring的配置文件配置多个数据源

     <!-- 数据源相同的内容 -->

Java代码   收藏代码
  1.     <bean id="parentDataSource"  
  2.         class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  3.         <property name="driverClass"  
  4.             value="oracle.jdbc.pool.OracleConnectionPoolDataSource" />  
  5.         <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl" />  
  6.         <property name="user" value="isc_v10" />  
  7.         <property name="password" value="isc" />  
  8.     </bean>  
  9.   
  10.     <!-- 数据源 -->  
  11.     <bean id="orclDataSource" parent="parentDataSource">  
  12.         <property name="user" value="orcl" />  
  13.         <property name="password" value="orcl" />  
  14.     </bean>  
  15.   
  16.     <!-- 数据源 -->  
  17.     <bean id="iscDataSource" parent="parentDataSource">  
  18.         <property name="user" value="isc_v10" />  
  19.         <property name="password" value="isc" />  
  20.     </bean>  
  21.   
  22.     <!-- 编写spring 配置文件的配置多数源映射关系 -->  
  23.     <bean id="dataSource" class="com.wy.config.DynamicDataSource">  
  24.         <property name="targetDataSources">  
  25.             <map key-type="java.lang.String">  
  26.                 <entry key="ORCL" value-ref="orclDataSource"></entry>  
  27.                 <entry key="ISC" value-ref="iscDataSource"></entry>  
  28.             </map>  
  29.         </property>  
  30.         <property name="defaultTargetDataSource" ref="orclDataSource">  
  31.         </property>  
  32.     </bean>  
  33.   
  34.     <bean id="sessionFactory"  
  35.         class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  36.         <property name="dataSource" ref="dataSource" />  
  37. </bean>  

 

5、使用

   @Test

Java代码   收藏代码
  1. public void testSave() {  
  2.     // hibernate创建实体  
  3.     DynamicDataSourceHolder.setDataSourceType(DynamicDataSourceGlobal.ORCL);// 设置为另一个数据源  
  4.     com.wy.domain.Test user = new com.wy.domain.Test();  
  5.   
  6.     user.setName("WY");  
  7.     user.setAddress("BJ");  
  8.   
  9.     testDao.save(user);// 使用dao保存实体  
  10.   
  11.     DynamicDataSourceHolder.setDataSourceType(DynamicDataSourceGlobal.ISC);// 设置为另一个数据源  
  12.   
  13.     testDao.save(user);// 使用dao保存实体到另一个库中  
  14.   
  15. }  
  1.        


spring 的AbstractRoutingDataSource解决了这个问题。

原理如图:

 

项目采用的是hibernate,直接在spring.xml设置sessionFactory的dataSource属性为动态数据源即可。

因为项目所有数据库结构都一致,为了避免每次设置数据源的时候要改一堆参数,修改了springAbstractRoutingDataSource类增加了一个getTargetDataSources方法,获取当前数据源详细信息,在其基础上修改数据库名称、用户名、密码即可,不用每次设置一堆参数。

Java代码   收藏代码
  1. Map<String, ComboPooledDataSource> targetDataSources = dynamicDataSource  
  2.                 .getTargetDataSources();  
  3.         if (targetDataSources == null) {  
  4.             targetDataSources = new HashMap<String, ComboPooledDataSource>();  
  5.             targetDataSources.put("baseDataSource", baseDataSource);  
  6.         }  
  7.         targetDataSources.put(dataSourceName, subSystemDataSource);  
  8.         dynamicDataSource.setTargetDataSources(targetDataSources);  
  9.         dynamicDataSource.afterPropertiesSet();  
 

另外,设置AbstractRoutingDataSource参数后要调用afterPropertiesSet()方法,spring容器才会进行加载操作。

 

在动态设置数据源方面,可以通过两种方式实现:

  1. 在action(项目使用struts)中进行设置,可以确保在每个servlet线程中数据源是一致的。
  2. 以aop方式,对service方法进行拦截,根据需求设置不同数据源。



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值