用spring 的AbstractRoutingDataSource解决了这个问题。
原理如图:
项目采用的是hibernate,直接在spring.xml设置sessionFactory的dataSource属性为动态数据源即可。
因为项目所有数据库结构都一致,为了避免每次设置数据源的时候要改一堆参数,修改了spring AbstractRoutingDataSource类增加了一个getTargetDataSources方法,获取当前数据源详细信息,在其基础上修改数据库名称、用户名、密码即可,不用每次设置一堆参数。
Map<String, ComboPooledDataSource> targetDataSources = dynamicDataSource
.getTargetDataSources();
if (targetDataSources == null) {
targetDataSources = new HashMap<String, ComboPooledDataSource>();
targetDataSources.put("baseDataSource", baseDataSource);
}
targetDataSources.put(dataSourceName, subSystemDataSource);
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.afterPropertiesSet();
另外,设置AbstractRoutingDataSource参数后要调用afterPropertiesSet()方法,spring容器才会进行加载操作。
在动态设置数据源方面,可以通过两种方式实现:
- 在action(项目使用struts)中进行设置,可以确保在每个servlet线程中数据源是一致的。
- 以aop方式,对service方法进行拦截,根据需求设置不同数据源。
转载:http://javasight.net/2011/11/spring-based-dynamic-datasource-implementation/