hibernate+spring 连接多个数据库,动态切换(多帐套)的实现
2013-06-14 12:31
681 查看
在现实应用中,可能我们后台所有连接的数据库可能不止一个,有可能要求一套代码同时可以连接多个数据库,并且要求在多个数据库中动态切换,本人也遇到这样的需求,就把自己的解决方案分享一下,该方法值针对hibernate+spring框架。
说先来说一下,我的这个需求:
先来讲一下帐套的概念:
按我的理解,帐套就是一个帐套就是一个数据库的映射。如后台有数据库a,b,c,那么我就建有一个映射
帐套a ---数据库a
帐套b---数据库b
帐套c---数据库c
用户看到的是帐套a,帐套b,帐套c,但是程序操作的数据库a,数据库b,数据库c,即当用户选择帐套a,程序对应的数据库就是数据库a,当用户选择帐套b,程序对应的数 据库就是b。
需求:
用户再登陆时,用户可以选择要登录的帐套(帐套就是一个队数据库的映射),要同时允许多个用户在登陆不同的帐套,也就是说程序对应的数据库,一直在不停地变化着,因为每个用户选择的帐套不同,程序操作的数据库就不同。
解决思路:
通过对需求分析,可以得到结论就是:每一个用户都操作着一个帐套,每一个帐套都对应着一个数据库,这里也可以说是一个对照表如:
用户1--帐套a
用户2--帐套b
根据帐套和数据库的映射,可以得到
用户1--数据库a
用户2--数据库b
因为我的是web应用,所以每一个用户就是一个会话(session),所以我用session的sessioinId作为用户的唯一标识。当用户在登陆系统时会被要求选择一个帐套,这个帐套会session绑在一起,作为一组键值对,存在放内存中,用户的每一次请求,都会根据sessionid获取到当前这个sessionId对应的帐套,进而获取到对应的数据库,然后将数据库切换为该sessionId 对应的数据。
原理都已经讲清楚,现在只需要实现2点,
1.记录每一个session对应的帐套
2.每一次请求切换对应的数据库
以下,讲一下如何实现这两点
记录每一个session对应的帐套
维护2个map,一个是当前线程map,另一个是sessionIdMap,在登陆时将用户信息和帐套信息写人
public class SpObserver {
/**
*description:
*@author lwq
*/
@SuppressWarnings("unchecked")
private static ThreadLocal local = new ThreadLocal();
@SuppressWarnings("unchecked")
//当前线程---数据库名称
public static void putSp(String dbName) {
local.set(dbName);
}
public static String getSp() {
return (String)local.get();
}
}
public class SessionMap {
/**
*description:
*@author lwq
*/
@SuppressWarnings("unchecked")
private static Map sessionMap=new HashMap();
@SuppressWarnings("unchecked")
public static void put(String sessionId,String dbName){
remove(sessionId);
sessionMap.put(sessionId, dbName);
}
public static void remove(String sessionId){
if(sessionMap.containsKey(sessionId)){
sessionMap.remove(sessionId);
}
}
public static String get(String sessionId){
if(sessionMap.containsKey(sessionId)){
String dbName=(String)sessionMap.get(sessionId);
return dbName;
}else{
return null;
}
}
//可以判断有多少个客户端
public static int getSize(){
return sessionMap.size();
}
}
切换数据库
配置dataSource
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="multiDataSource" class="com.onesun.common.system.MultiDataSource">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
在实现一个BasicDataSource,
public class MultiDataSource implements DataSource,ApplicationContextAware{
....
public DataSource getDataSource(){
String sp = SpObserver.getSp();
String dbName=SessionMap.get(sp);
return getDataSource(dbName);
}
public DataSource getDataSource(String dbName) {
System.out.println("数据库:"+dbName);
try{
if(dbName==null||dbName.equals("")){
return this.dataSource;
}
return (DataSource)this.applicationContext.getBean(dbName);
}catch(Exception e ){
try{
return this.loadDataSource(dbName);
}catch(Exception e2){
return this.createDataSource(dbName);
}
}
}
...
}
dbName就是数据库名称,应该还要对应着一个dbName.xml内容如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="wxtl" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/dbName"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
</beans>
以上都只是一个思路,没有完整的代码,希望能给正在寻求解决方案的朋友帮助
说先来说一下,我的这个需求:
先来讲一下帐套的概念:
按我的理解,帐套就是一个帐套就是一个数据库的映射。如后台有数据库a,b,c,那么我就建有一个映射
帐套a ---数据库a
帐套b---数据库b
帐套c---数据库c
用户看到的是帐套a,帐套b,帐套c,但是程序操作的数据库a,数据库b,数据库c,即当用户选择帐套a,程序对应的数据库就是数据库a,当用户选择帐套b,程序对应的数 据库就是b。
需求:
用户再登陆时,用户可以选择要登录的帐套(帐套就是一个队数据库的映射),要同时允许多个用户在登陆不同的帐套,也就是说程序对应的数据库,一直在不停地变化着,因为每个用户选择的帐套不同,程序操作的数据库就不同。
解决思路:
通过对需求分析,可以得到结论就是:每一个用户都操作着一个帐套,每一个帐套都对应着一个数据库,这里也可以说是一个对照表如:
用户1--帐套a
用户2--帐套b
根据帐套和数据库的映射,可以得到
用户1--数据库a
用户2--数据库b
因为我的是web应用,所以每一个用户就是一个会话(session),所以我用session的sessioinId作为用户的唯一标识。当用户在登陆系统时会被要求选择一个帐套,这个帐套会session绑在一起,作为一组键值对,存在放内存中,用户的每一次请求,都会根据sessionid获取到当前这个sessionId对应的帐套,进而获取到对应的数据库,然后将数据库切换为该sessionId 对应的数据。
原理都已经讲清楚,现在只需要实现2点,
1.记录每一个session对应的帐套
2.每一次请求切换对应的数据库
以下,讲一下如何实现这两点
记录每一个session对应的帐套
维护2个map,一个是当前线程map,另一个是sessionIdMap,在登陆时将用户信息和帐套信息写人
public class SpObserver {
/**
*description:
*@author lwq
*/
@SuppressWarnings("unchecked")
private static ThreadLocal local = new ThreadLocal();
@SuppressWarnings("unchecked")
//当前线程---数据库名称
public static void putSp(String dbName) {
local.set(dbName);
}
public static String getSp() {
return (String)local.get();
}
}
public class SessionMap {
/**
*description:
*@author lwq
*/
@SuppressWarnings("unchecked")
private static Map sessionMap=new HashMap();
@SuppressWarnings("unchecked")
public static void put(String sessionId,String dbName){
remove(sessionId);
sessionMap.put(sessionId, dbName);
}
public static void remove(String sessionId){
if(sessionMap.containsKey(sessionId)){
sessionMap.remove(sessionId);
}
}
public static String get(String sessionId){
if(sessionMap.containsKey(sessionId)){
String dbName=(String)sessionMap.get(sessionId);
return dbName;
}else{
return null;
}
}
//可以判断有多少个客户端
public static int getSize(){
return sessionMap.size();
}
}
切换数据库
配置dataSource
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="multiDataSource" class="com.onesun.common.system.MultiDataSource">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
在实现一个BasicDataSource,
public class MultiDataSource implements DataSource,ApplicationContextAware{
....
public DataSource getDataSource(){
String sp = SpObserver.getSp();
String dbName=SessionMap.get(sp);
return getDataSource(dbName);
}
public DataSource getDataSource(String dbName) {
System.out.println("数据库:"+dbName);
try{
if(dbName==null||dbName.equals("")){
return this.dataSource;
}
return (DataSource)this.applicationContext.getBean(dbName);
}catch(Exception e ){
try{
return this.loadDataSource(dbName);
}catch(Exception e2){
return this.createDataSource(dbName);
}
}
}
...
}
dbName就是数据库名称,应该还要对应着一个dbName.xml内容如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="wxtl" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/dbName"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
</beans>
以上都只是一个思路,没有完整的代码,希望能给正在寻求解决方案的朋友帮助
相关文章推荐
- Spring+Hibernate下的数据库连接动态切换
- spring+hibernate+mysql实现主从数据库动态切换
- 在Hibernate里面动态切换SChema实现访问不同的数据库的几种方法
- 利用AbstractRoutingDataSource实现动态数据源切换 (Spring+Hibernate)
- 在Hibernate里面动态切换SChema实现访问不同的数据库的几种方法
- Spring boot + maven + hibernate 实现数据库连接、查询
- Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)
- Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)
- Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)
- spring 集成hibernate 连接多数据库 java BaseDao 实现
- Spring+Hibernate实现动态SessionFactory切换(改进版)
- Spring整合Hibernate动态切换SessionFactory (切换数据库方言)
- Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源
- 利用AbstractRoutingDataSource实现动态数据源切换 (一、Spring+Hibernate)
- Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源
- 利用AbstractRoutingDataSource实现动态数据源切换 (Spring+Hibernate)
- hibernate连接多个数据库,如何动态切换(我一般用配置文件动态切换)
- Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)
- 实现spring+mybatis+uncode dal,应用自动切换连接数据库
- Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)