首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > Java Web开发 >

Spring动态添加使用数据源,该如何处理

2014-01-13 
Spring动态添加使用数据源单位项目有个需求,我描述一下,希望会的人 ,帮忙指导一下公司注册时,系统给该公司

Spring动态添加使用数据源
单位项目有个需求,我描述一下,希望会的人 ,帮忙指导一下
公司注册时,系统给该公司创建一个数据库,同时使用该数据库创建数据源,动态加载到内存.
公司用户登录时,根据登陆信息,判断该公司对应的数据源,切换到使用对应的数据源.该登录的用户操作过程中产生的业务数据都保存在对应的数据库中.
下边是我的实现思路,参考http://www.iteye.com/topic/72486
1.相关的配置文件
Spring动态添加使用数据源,该如何处理
Spring动态添加使用数据源,该如何处理
Spring动态添加使用数据源,该如何处理
2.用户注册时,产生一个spring配置文件,该文件就是一个数据源的配置信息,如图:
Spring动态添加使用数据源,该如何处理
配置文件产生后,新建一个数据,最后将该配置文件加载到内存中,代码如图:
Spring动态添加使用数据源,该如何处理
3.编写一个获得和设置上下文环境的类,主要负责改变上下文数据源的名称
Spring动态添加使用数据源,该如何处理
4.编写一个动态数据源类

public class DynamicDataSource extends AbstractRoutingDataSource {

/* 
 * 该方法必须要重写  方法是为了根据数据库标示符取得当前的数据库
 */
@Override
public Object determineCurrentLookupKey() {
DataSourceType dataSourceType= DataSourceContextHolder.getDataSourceType();
return dataSourceType;
}

@Override
public void setDataSourceLookup(DataSourceLookup dataSourceLookup) {
super.setDataSourceLookup(dataSourceLookup);
}

@Override
public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
}

@Override
public void setTargetDataSources(Map targetDataSources) {
super.setTargetDataSources(targetDataSources);
}

}

5.最后开始简单的测试
@Test
public void test() {
try {
List<UserinfoEntity> list = userInfoService.getList(UserinfoEntity.class);
System.out.println(list.size());

String dataSourceName = "qqq";
String url = "jdbc:mysql://127.0.0.1:3306/mos_saas_test";
String username = "root";
String password = "root";
ConfigFileCreator.createConfigFile(dataSourceName, url, username, password);
DynamicLoadBean dynamicBeanLoad =(DynamicLoadBean)SpringContextUtil.getBean("dynamicLoadBean");   
dynamicBeanLoad.loadBean("classpath:mos/qqq.xml"); 
//dynamicBeanLoad.registBean(dataSourceName, "parentDataSource");
DruidDataSource dds = (DruidDataSource) SpringContextUtil.getBean(dataSourceName);
DynamicDataSource ds = (DynamicDataSource)SpringContextUtil.getBean("dataSource");
//Map targetDataSources = new HashMap();
//targetDataSources.put(DataSourceType.qqq, dds);
//
//ds.setTargetDataSources(targetDataSources);
//DataSourceLookup dataSourceLookup = new MapDataSourceLookup();
//dataSourceLookup.getDataSource("qqq");
//
//ds.setDataSourceLookup(dataSourceLookup);

DataSourceContextHolder.setDataSourceType(DataSourceType.qqq);

List<UserinfoEntity> list2 = userInfoService.getList(UserinfoEntity.class);
System.out.println(list2.size());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

结果是数据源确实改变了,但是对数据库的操作还是基于默认数据源的,不知道怎么回事,求技术大牛给予帮助
[解决办法]
你的sessionfactory 还是最开始那个。
你新加的spring配置文件只配置了一个数据源,sessionFactory没变。

你需要创建不同的sessionFactory。
根据数据源来创建。

[解决办法]
sessionFactory没有改变,需要在生成一个sessionFactory,多数据源还要考虑事物的问题,tomcat对多数据源事物支持不是太好
[解决办法]
又看到一个在spring里使用ThreadLocal作为路由数据源实现方式的案例。
这种实现在普通情况下确实能通过取当前线程实现数据源的定位,但是如果应用存在使用spring事务的情况,这么做就是在挖地雷。
因为spring推荐的scope prototype模式下bean都是单例,并发的时候依靠spring内部的ThreadLocal切换各个线程的参数,而spring的事务机制会针对每一个事务新开一个线程,最后导致在有事务的情况下,spring内部的事务线程和自定义路由使用的数据源定位线程不一致,数据源定位失败。
表现出来的现象就是,一个有spring事务的servcie里,无法调用两个数据源,无论怎么配置都会导致数据源被路由到同一个线程。

热点排行