起因:

公司的当前产品,主要是两个项目集成的,一个是java项目,还有一个是php项目,两个项目用的是不同的数据源,但都是mysql数据库,因为java这边的开发工作已经基本完成了,而php那边任务还很多,人手也比较紧,产品上线日期紧促,所以领导希望java这边能够帮助php那边写接口,所以需要切换数据源

思路:

动态切换数据源确切的来说是在同一类型数据库的情况下的。意思就是说 , 在系统中的使用的数据库分布在多台数据库服务器或者在同台服务器上的多个数据库. 在运行时期间根据某种标识符来动态的选择当前操作的数据库.
     1.数据源是相同类型的数据库: 一个SessionFactory+动态数据源+一个事务管理器
     2.数据源是不同类型的数据库: 根据类型 配置多套SessionFactory

困难解决:

1、配置dataSource的时候将id写成那么,而动态数据源的设置引用的是id

2、动态数据源的切换不能用枚举来标识,得用常量

3、在mysql数据库中不同种类的table也照样起作用

4、spring的事务处理可能会影响动态数据源的切换(尚未发现该问题)

测试环境:

1、hibernate

2、spring

3、mysql

最终实现:

1、首先得配置多个数据源

<!-- 配置数据源 使用的是Druid数据源 -->
<bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url1}" />
<property name="username" value="${jdbc.username1}" />
<property name="password" value="${jdbc.password1}" /> <!-- 初始化连接大小 -->
<property name="initialSize" value="0" />
<!-- 连接池最大使用连接数量 -->
<property name="maxActive" value="20" /> <!-- 连接池最小空闲 -->
<property name="minIdle" value="0" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize"
value="33" />
<!-- 用来检测有效sql -->
<property name="validationQuery" value="${validationQuery}" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="testWhileIdle" value="true" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="25200000" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="true" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="1800" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="true" />
<!-- 监控数据库 -->
<property name="filters" value="mergeStat" />
</bean> <!-- 配置数据源 使用的是Druid数据源 -->
<bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url2}" />
<property name="username" value="${jdbc.username2}" />
<property name="password" value="${jdbc.password2}" /> <!-- 初始化连接大小 -->
<property name="initialSize" value="0" />
<!-- 连接池最大使用连接数量 -->
<property name="maxActive" value="20" /> <!-- 连接池最小空闲 -->
<property name="minIdle" value="0" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize"
value="33" />
<!-- 用来检测有效sql -->
<property name="validationQuery" value="${validationQuery}" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="testWhileIdle" value="true" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="25200000" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="true" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="1800" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="true" />
<!-- 监控数据库 -->
<property name="filters" value="mergeStat" />
</bean>

然后配置多数据源映射关系

<!-- 编写spring 配置文件的配置多数源映射关系 -->
<bean id="dataSource" class="com.asen.util.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="CCVZB" value-ref="dataSource1"></entry>
<entry key="CCSC" value-ref="dataSource2"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSource1"></property>
</bean>

然后是hibernate的SessionFactory

<!-- 配置hibernate的SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- 注入数据源 相关信息看源码 -->
<property name="dataSource" ref="dataSource" />
<!-- hibernate配置信息 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
</props>
</property>
<!-- 扫描hibernate注解配置的entity -->
<property name="packagesToScan" value="com.asen.app.*" />
</bean>

这样配置文件就写好了,但是还需要三个类

package com.asen.util;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDataSourceType();
} }
package com.asen.util;

public class DynamicDataSourceGlobal {
public static final String CCVZB="CCVZB";
public static final String CCSC="CCSC";
}
package com.asen.util;

public class DynamicDataSourceHolder {
// 线程本地环境
private static final ThreadLocal contextHolder = new ThreadLocal(); // 设置数据源类型
public static void setDataSourceType(String dataSourceType) {
contextHolder.set(dataSourceType);
} // 获取数据源类型
public static String getDataSourceType() {
return (String) contextHolder.get();
} // 清除数据源类型
public static void clearDataSourceType() {
contextHolder.remove();
} }

具体切换

package com.asen.app.dao.impl;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository; import com.asen.app.dao.IHomeFunctionDao;
import com.asen.util.DynamicDataSourceGlobal;
import com.asen.util.DynamicDataSourceHolder; @Repository("homeFunctionDao")
public class HomeFunctionDaoImpl extends HibernateDaoSupport implements IHomeFunctionDao { @Resource
public void setSessionFacotry(SessionFactory sessionFacotry) {
super.setSessionFactory(sessionFacotry);
} @Override
public List getHomeFunctionList() throws Exception {
DynamicDataSourceHolder.setDataSourceType(DynamicDataSourceGlobal.CCVZB);
SessionFactory sessionFactory = getHibernateTemplate().getSessionFactory();
Session session = sessionFactory.openSession();
Query query = session.createQuery("from HomeFunction");
return query.list();
}
}

hibernate动态切换数据源的更多相关文章

  1. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  2. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  3. Spring + Mybatis 项目实现动态切换数据源

    项目背景:项目开发中数据库使用了读写分离,所有查询语句走从库,除此之外走主库. 最简单的办法其实就是建两个包,把之前数据源那一套配置copy一份,指向另外的包,但是这样扩展很有限,所有采用下面的办法. ...

  4. 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法

    相关项目地址:https://github.com/helloworlde/SpringBoot-DynamicDataSource 1. org.apache.ibatis.binding.Bind ...

  5. Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

  6. Spring+Mybatis动态切换数据源

    功能需求是公司要做一个大的运营平台: 1.运营平台有自身的数据库,维护用户.角色.菜单.部分以及权限等基本功能. 2.运营平台还需要提供其他不同服务(服务A,服务B)的后台运营,服务A.服务B的数据库 ...

  7. 基于AbstractRoutingDataSource实现动态切换数据源

    基于AbstractRoutingDataSource实现动态切换数据源 /**  * DataSource注解接口  */ @Target({ElementType.TYPE, ElementTyp ...

  8. Spring动态切换数据源及事务

    前段时间花了几天来解决公司框架ssm上事务问题.如果不动态切换数据源话,直接使用spring的事务配置,是完全没有问题的.由于框架用于各个项目的快速搭建,少去配置各个数据源配置xml文件等.采用了动态 ...

  9. AOP获取方法注解实现动态切换数据源

    AOP获取方法注解实现动态切换数据源(以下方式尚未经过测试,仅提供思路) ------ 自定义一个用于切换数据源的注解: package com.xxx.annotation; import org. ...

随机推荐

  1. GitHub优秀的Android 开源项目

    GitHub上优秀Android开源项目 转载自 : http://my.eoe.cn/sisuer/archive/3348.html http://my.eoe.cn/sisuer/archive ...

  2. 如何开发一个微信小程序

    一.概述     特点:对商家来说,小程序的开发成本低(有丰富的组件.api等).运营成本低(有数据日志等).稳定.互动流畅,便于分享.传播(基本微信平台的大量用户).对用户来说,扫码即可获取服务,随 ...

  3. Python3基础 set() 删除一个列表中的重复项

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  4. 一段神奇的代码-关于PHP字符变量奇怪现象的解释

    首先神奇的PHP是支持字符数据类型的,有同学就写了这样一段代码: for ($c = 'a'; $c <= 'z'; $c++) { echo $c . ' '; } 然而结果却不是他想要的a到 ...

  5. Android应用性能优化方案

    1.避免创建不必要的对象 2.如果方法用不到成员变量,可以把方法声明为静态(static),这样性能会提高百分之十五到百分之二十 3.避免使用get/set存取字段,可以把字段声明为public直接访 ...

  6. Java语言与C语言之间的应用比较

    http://book.51cto.com/art/200906/131809.htm C语言能干的Java也能干的如下: 网络应用层协议服务程序开发:如WebServer.FTPServer.Mai ...

  7. iOS 之 NSUserDefault

    1. 概念 NSUserDefaults是一种特殊的property list.是系统封装的属性列表,方便记录简单的数据. 2. 使用说明 2.1. 创建NSUserDefaults NSUserDe ...

  8. ThinkPHP 3 MVC模式和URL访问

    一.什么是MVC                 //了解    M -Model 编写model类 对数据进行操作    V -View  编写html文件,页面呈现    C -Controlle ...

  9. HDU5882

    Balanced Game Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  10. Linux 服务器设置成支持中文

    Linux 服务器设置成支持中文 由于服务器默认是不支持中文的.所以一般需要单独设置一下. 检查本机已有的语言包 locale -a 默认是没有中文的,所以会显示: C C.UTF-8 POSIX e ...