起因:在当前我手上的一个项目中需要多个数据源,并且来自于不同类型的数据库... 因为很多历史原因.这个项目的住数据源是MySQL,整个系统的CURD都是操作的这个数据库.

但是还有另外两个用于数据采集的数据库: MSSQL,ACCESS.还好只是用于数据采集,在事务上可以不要跨数据库了,这一点节省了好多的工作量.

环境:我搭建的测试环境是 spring2.5.6+hibernate3.2
思路:动态切换数据源确切的来说是在同一类型数据库的情况下的。意思就是说 , 在系统中的使用的数据库分布在多台数据库服务器或者在同台服务器上的多个数据库. 在运行时期间根据某种标识符来动态的选择当前操作的数据库.
1.数据源是相同类型的数据库: 一个SessionFactory+动态数据源+一个事务管理器
2.数据源是不同类型的数据库: 根据类型 配置多套SessionFactory
模拟:两个mysql数据源+一个Access数据源
实现
1.切换数据源需要标识符,标识符是Object类型
package lhp.example.context;public enum DBType { dataSource1, dataSource2;}

2.然后创建一个用于切换数据源(设置或者获得上下文)的工具类
package lhp.example.context;public class ContextHolder {private static final ThreadLocal<Object> holder = new ThreadLocal<Object>();public static void setDbType(DBType dbType) {holder.set(dbType);}public static DBType getDbType() {return (DBType) holder.get();}public static void clearDbType() {holder.remove();}
}

3.创建动态数据源类,继承org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource这个类.
package lhp.example.context;import java.util.logging.Logger;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;public class DynamicDataSource extends AbstractRoutingDataSource {public static final Logger logger = Logger.getLogger(DynamicDataSource.class.toString());@Overrideprotected Object determineCurrentLookupKey() {DBType key = ContextHolder.getDbType();//获得当前数据源标识符//logger.info("当前数据源 :" + key);return key;}}

4.然后配置多个数据源
<!-- 数据源1 : mysql --><bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver" /><property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/dec" /><property name="user" value="root" /><property name="password" value="" /></bean><!-- 数据源2 : mysql  --><bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver" /><property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/lms" /><property name="user" value="root" /><property name="password" value="" /></bean><!-- 数据源3 :  access --><bean id="dataSource3" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="sun.jdbc.odbc.JdbcOdbcDriver" /><property name="jdbcUrl" value="jdbc:odbc:accessTest" /><property name="user" value="administrator" /><property name="password" value="XLZX0309" /></bean><!-- mysql 动态数据源设置--><bean id="mysqlDynamicDataSource" class="lhp.example.context.DynamicDataSource"><property name="targetDataSources"><!-- 标识符类型 --><map key-type="lhp.example.context.DBType"><entry key="dataSource1" value-ref="dataSource1" /><entry key="dataSource2" value-ref="dataSource2" /></map></property><property name="defaultTargetDataSource" ref="dataSource1" /></bean>

5.配置sessionFactory
<!-- mysql sessionFactory --><bean id="mysqlSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"><property name="dataSource" ref="mysqlDynamicDataSource" /><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key="hibernate.show_sql">true</prop><prop key="hibernate.hbm2ddl.auto">update</prop><!--create validate --><prop key="hibernate.query.substitutions">true 1, false 0</prop></props></property></bean><!-- access sessionFactory --><bean id="aceessSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"><property name="dataSource" ref="dataSource3" /><property name="hibernateProperties"><props><!-- access 语法和MSSQL相似 所以用的MSSQL方言,或者可以使用第三方方言 --><prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop><prop key="hibernate.jdbc.batch_size">30</prop><prop key="hibernate.jdbc.fetch_size">50</prop><prop key="hibernate.show_sql">true</prop><prop key="hibernate.format_sql">false</prop><prop key="hibernate.hbm2ddl.auto">update</prop><!--create validate --><prop key="hibernate.query.substitutions">true 1, false 0</prop><prop key="hibernate.cglib.use_reflection_optimizer">true</prop><!-- <prop key="hibernate.cache.use_second_level_cache">true</prop> --><!-- <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> --><!-- <prop key="hibernate.cache.use_query_cache">true</prop> --><!-- <prop key="hibernate.generate_statistics">true</prop> --><!-- <prop key="hibernate.cache.provider_configuration_file_resource_path">classpath:ehcache.xml</prop> --></props></property></bean>

6.测试用例
package lhp.example.junit;import static org.junit.Assert.*;
import java.sql.DatabaseMetaData;
import lhp.example.context.ContextHolder;
import lhp.example.context.DBType;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class ServiceTest {private ApplicationContext context;//三个数据源的URLprivate String dataSource1_URL = "jdbc:mysql://127.0.0.1:3306/dec";private String dataSource2_URL = "jdbc:mysql://127.0.0.1:3306/lms";private String dataSource3_URL = "jdbc:odbc:accessTest";private SessionFactory mysqlSessionFactory;private SessionFactory aceessSessionFactory;@Beforepublic void setUp() throws Exception {// 选择数据源初始化spring
        ContextHolder.setDbType(DBType.dataSource1);//
        String[] xmlFiles = new String[] { "applicationContext-dataSource.xml","applicationContext-hibernate.xml","applicationContext-spring.xml" };//
        context = new ClassPathXmlApplicationContext(xmlFiles);//
        mysqlSessionFactory = (SessionFactory) context.getBean("mysqlSessionFactory");aceessSessionFactory = (SessionFactory) context.getBean("aceessSessionFactory");}@SuppressWarnings("deprecation")@Testpublic void mysqlDataSourceTest() {try {Session mysqlSession = mysqlSessionFactory.openSession();// 获得数据库元数据DatabaseMetaData meatData = mysqlSession.connection().getMetaData();// 默认启动数据源 dataSource1//断言当前数据源URL是否是dataSource1的URL
            assertEquals(dataSource1_URL, meatData.getURL());// 切换到数据源 dataSource2
            ContextHolder.setDbType(DBType.dataSource2);mysqlSession = mysqlSessionFactory.openSession();meatData = mysqlSession.connection().getMetaData();//断言当前数据源URL是否是dataSource2的URL
            assertEquals(dataSource2_URL, meatData.getURL());} catch (Exception e) {e.printStackTrace();}}@SuppressWarnings("deprecation")@Testpublic void accessDataSourceTest() {try {Session accessSession = aceessSessionFactory.openSession();// 获得数据库元数据DatabaseMetaData meatData = accessSession.connection().getMetaData();//断言当前数据源URL是否是dataSource3的URL
            assertEquals(dataSource3_URL, meatData.getURL());} catch (Exception e) {e.printStackTrace();}}}

7.测试结果

转载于:https://www.cnblogs.com/lowerCaseK/archive/2013/04/18/ChangeDataSource.html

动态切换数据源(spring+hibernate)相关推荐

  1. spring boot 动态切换数据源实现多租户开发

    之前的文章有介绍过spring boot 动态切换数据源spring boot 动态切换数据源(数据源信息从数据库中读取)_lgq2016的博客-CSDN博客,今天简单介绍一下动态数据源切换实战,主要 ...

  2. mybatis手动切换数据库_在Spring项目中使用 Mybatis 如何实现动态切换数据源

    在Spring项目中使用 Mybatis 如何实现动态切换数据源 发布时间:2020-11-17 16:20:11 来源:亿速云 阅读:108 作者:Leah 这篇文章将为大家详细讲解有关在Sprin ...

  3. Spring Boot多数据源配置并通过注解实现动态切换数据源

    文章目录 1. AbstractRoutingDataSource类介绍 2. ThreadLocal类介绍 3. 环境准备 3.1 数据库准备 3.2 项目创建 4. 具体实现 4.1 定义数据源枚 ...

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

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

  5. Java实现动态切换数据源

    在一般的Java项目中,如果使用Spring去管理数据库连接信息,一般只能连接一个数据库,可是会有部分情况我们需要连接多个数据库,甚至还会存在不同的请求需要根据配置信息连接不同的数据库,比如: 在很多 ...

  6. springboot 中动态切换数据源(多数据源应用设计)

    目录 原理图 数据库 项目结构 启动类 entity controller service mapper 配置文件 线程上下文 (DataSourceHolder) 动态数据源 DynamicData ...

  7. 通过切面动态切换数据源

    标题业务场景:大量的项目的数据库需要从db2迁移到oracle,为项目上线后出现不可预料的错误可及时回退,需要可以随时切换数据源 以控制层为切点,动态切换数据源,通过查询数据库查询当前应用的开关,来判 ...

  8. Springboot/MybatisPlus动态切换数据源

    1.1 简述 最近项目中有动态切换数据源需求,主要是要动态切换数据源进行数据的获取,现将项目中实现思路及代码提供出来,供大家参考.当然切换数据源还有其他的方式比如使用切面的方式,其实大体思路是一样的. ...

  9. SpringBoot+AOP实现动态切换数据源

    首先描述下笔者的基本步骤: 1.yml配置文件中定义多数据源: 2.自定义一个注解类(@DataSource 可标注在类或方法上),定义String类型的变量value,value中存储数据源名称: ...

最新文章

  1. 增大iphone音量技巧_就算我们把手机音量开到最大!外放声音还是小,那是这个设置没开...
  2. few-shot learning 1.1——零样本学习
  3. WebService客户端开发(Axis2 1.5)
  4. sql中实现取得某字段中数字值
  5. 内存属于linux文件吗,linux下的/dev/shm是什么? 内存 文件系统
  6. 《Python黑帽子:黑客与渗透测试编程之道》 Web攻击
  7. Navicat Premium 安装
  8. wincc怎么做一个弹出画面_wincc怎样弹出确认窗口?
  9. C++继承机制(中篇)
  10. java jdk1 5手机版,java jdk1.7|java7_绿茶手机网
  11. mysql命令成功数值不变_MySQL基础知识精华汇总_3(mysql基础命令操作)
  12. Flex布局新旧混合写法详解(兼容微信)
  13. linux管理员基础知识
  14. 设备综合效率(OEE)的计算方法
  15. powershell自定义字体
  16. 图书销售管理系统的设计与实现
  17. java开发面试复试_【java开发初轮技术面试以后 复试一般问什么?】-看准网
  18. 开放式办公室不利心理健康:噪音大且效率低
  19. 深入剖析智能仓储管理(WMS)应用价值与应用场景
  20. P1346 电车(floyd)

热门文章

  1. mysql常见的运算符及使用
  2. css①字体颜色正常显示,背景透明②字体颜色与背景均为透明的设置方法
  3. thinkphp3.2 代码生成并点击验证码
  4. 【读书笔记】并发编程需要注意的几个典型问题
  5. 业内人士惊暴网络求职黑幕!
  6. 眼花缭乱的数据库,怎样选择?给你这个书单,想学哪个学哪个
  7. 智能驾驶系统是怎样看懂交通标志的?3张流程图给你讲明白
  8. 百度吹过的牛实现了,你的呢?5本书带你搞定AI前沿技术
  9. 微软打脸,Windows 7 再次成为微软的头号桌面操作系统
  10. 为什么不可以使用哈曼顿距离_哈曼卡顿SOUNDSTICKS4全新一代无线水晶蓝牙音箱评测...