利用AbstractRoutingDataSource实现动态数据源切换 (Spring+Hibernate)
转载
Spring配置多数据源的方式和具体使用过程
1、数据源的名称常量类
public enum DynamicDataSourceGlobal {
2、建立一个获得和设置上下文环境的类,主要负责改变上下文数据源的名称
public class DynamicDataSourceHolder {
1. // 线程本地环境
2. private static final ThreadLocal<DynamicDataSourceGlobal> contextHolder = new
3.
4. // 设置数据源类型
5. public static void
6. "DataSourceType cannot be null");
7. contextHolder.set(dataSourceType);
8. }
9.
10. // 获取数据源类型
11. public static
12. return
13. }
14.
15. // 清除数据源类型
16. public static void
17. contextHolder.remove();
18. }
3、建立动态数据源类,注意,这个类必须继承AbstractRoutingDataSource,且实现方法 determineCurrentLookupKey,该方法返回一个Object,一般是返回字符串
public class DynamicDataSource extends AbstractRoutingDataSource {
1. @Override
2. protected
3. return
4. }
5.
6. }
4、编写spring的配置文件配置多个数据源
<!-- 数据源相同的内容 -->
1. "parentDataSource"
2. class="org.springframework.jdbc.datasource.DriverManagerDataSource">
3. "driverClass"
4. "oracle.jdbc.pool.OracleConnectionPoolDataSource"
5. "url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"
6. "user" value="isc_v10"
7. "password" value="isc"
8. </bean>
9.
10. <!-- 数据源 -->
11. "orclDataSource" parent="parentDataSource">
12. "user" value="orcl"
13. "password" value="orcl"
14. </bean>
15.
16. <!-- 数据源 -->
17. "iscDataSource" parent="parentDataSource">
18. "user" value="isc_v10"
19. "password" value="isc"
20. </bean>
21.
22. <!-- 编写spring 配置文件的配置多数源映射关系 -->
23. "dataSource" class="com.wy.config.DynamicDataSource">
24. "targetDataSources">
25. "java.lang.String">
26. "ORCL" value-ref="orclDataSource"></entry>
27. "ISC" value-ref="iscDataSource"></entry>
28. </map>
29. </property>
30. "defaultTargetDataSource" ref="orclDataSource">
31. </property>
32. </bean>
33.
34. "sessionFactory"
35. class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
36. "dataSource" ref="dataSource"
37. </bean>
5、使用
@Test

1. public void
2. // hibernate创建实体
3. // 设置为另一个数据源
4. new
5.
6. "WY");
7. "BJ");
8.
9. // 使用dao保存实体
10.
11. // 设置为另一个数据源
12.
13. // 使用dao保存实体到另一个库中
14.
15. }
spring 的AbstractRoutingDataSource解决了这个问题。
原理如图:

spring.xml设置sessionFactory的dataSource属性为动态数据源即可。
springAbstractRoutingDataSource类增加了一个getTargetDataSources方法,获取当前数据源详细信息,在其基础上修改数据库名称、用户名、密码即可,不用每次设置一堆参数。

1. Map<String, ComboPooledDataSource> targetDataSources = dynamicDataSource
2. .getTargetDataSources();
3. if (targetDataSources == null) {
4. new
5. "baseDataSource", baseDataSource);
6. }
7. targetDataSources.put(dataSourceName, subSystemDataSource);
8. dynamicDataSource.setTargetDataSources(targetDataSources);
9. dynamicDataSource.afterPropertiesSet();
AbstractRoutingDataSource参数后要调用afterPropertiesSet()方法,spring容器才会进行加载操作。
在动态设置数据源方面,可以通过两种方式实现:
- 在action(项目使用struts)中进行设置,可以确保在每个servlet线程中数据源是一致的。
- 以aop方式,对service方法进行拦截,根据需求设置不同数据源。