Spring动态切换多数据源解决方案

spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性。而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据。

Spring2.x以后的版本中采用Proxy模式,就是我们在方案中实现一个虚拟的数据源,并且用它来封装数据源选择逻辑,这样就可以有效地将数据源选择逻辑从Client中分离出来。Client提供选择所需的上下文(因为这是Client所知道的),由虚拟的DataSource根据Client提供的上下文来实现数据源的选择。

实现

具体的实现就是,虚拟的DataSource仅需继承AbstractRoutingDataSource实现determineCurrentLookupKey()在其中封装数据源的选择逻辑。

一、动态配置多数据源

1. 数据源的名称常量类:

[java] view plain copy

print?

  1. /**
  2. * 动态配置多数据源
  3. * 数据源的名称常量类
  4. * @author LONGHUI_LUO
  5. *
  6. */
  7. public class DataSourceConst {
  8. public static final String TEST="test";
  9. public static final String USER="User";
  10. }

2. 建立一个获得和设置上下文环境的类,主要负责改变上下文数据源的名称:

[java] view plain copy

print?

  1. /**
  2. * 获得和设置上下文环境 主要负责改变上下文数据源的名称
  3. *
  4. * @author LONGHUI_LUO
  5. *
  6. */
  7. public class DataSourceContextHolder {
  8. private static final ThreadLocal contextHolder = new ThreadLocal(); // 线程本地环境
  9. // 设置数据源类型
  10. public static void setDataSourceType(String dataSourceType) {
  11. contextHolder.set(dataSourceType);
  12. }
  13. // 获取数据源类型
  14. public static String getDataSourceType() {
  15. return (String) contextHolder.get();
  16. }
  17. // 清除数据源类型
  18. public static void clearDataSourceType() {
  19. contextHolder.remove();
  20. }
  21. }

3. 建立动态数据源类,注意,这个类必须继承AbstractRoutingDataSource,且实现方法determineCurrentLookupKey,该方法返回一个Object,一般是返回字符串:

[java] view plain copy

print?

  1. /**
  2. * 建立动态数据源
  3. *
  4. * @author LONGHUI_LUO
  5. *
  6. */
  7. public class DynamicDataSource extends AbstractRoutingDataSource {
  8. protected Object determineCurrentLookupKey() {
  9. // 在进行DAO操作前,通过上下文环境变量,获得数据源的类型
  10. return DataSourceContextHolder.getDataSourceType();
  11. }
  12. }

4. 编写spring的配置文件配置多个数据源

[html] view plain copy

print?

  1. <!-- 数据源相同的内容 -->
  2. <bean
  3. id="parentDataSource"
  4. class="org.apache.commons.dbcp.BasicDataSource"
  5. destroy-method="close">
  6. <property
  7. name="driverClassName"
  8. value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
  9. <property name="username" value="sa" />
  10. <property name="password" value="net2com" />
  11. </bean>

[html] view plain copy

print?

  1. <!-- start以下配置各个数据源的特性 -->
  2. <bean parent="parentDataSource" id="testDataSource">
  3. <propertynamepropertyname="url" value="jdbc:sqlserver://localhost:1433;databaseName=test" />
  4. </bean>
  5. <bean parent="parentDataSource" id="UserDataSource">
  6. <property
  7. name="url"
  8. value="jdbc:sqlserver://localhost:1433;databaseName=User" />
  9. </bean>

[html] view plain copy

print?

  1. <!-- end 配置各个数据源的特性 -->

5. 编写spring配置文件配置多数据源映射关系

[html] view plain copy

print?

  1. <bean class="com.xxxx.datasouce.DynamicDataSource" id="dataSource">
  2. <property name="targetDataSources">
  3. <map key-type="java.lang.String">
  4. <entry value-ref="testDataSource" key="test"></entry>
  5. <entry value-ref="UserDataSource" key="User"></entry>
  6. </map>
  7. </property>
  8. <property name="defaultTargetDataSource" ref="testDataSource" ></property>
  9. </bean>

在这个配置中第一个property属性配置目标数据源,<map key-type="Java.lang.String">中的key-type必须要和静态键值对照类DataSourceConst中的值的类型相 同;<entry key="User" value-ref="userDataSource"/>中key的值必须要和静态键值对照类中的值相同,如果有多个值,可以配置多个< entry>标签。第二个property属性配置默认的数据源。

动态切换是数据源

[java] view plain copy

print?

  1. DataSourceContextHolder.setDataSourceType(DataSourceConst.TEST);

该方案的优势

首先,这个方案完全是在spring的框架下解决的,数据源依然配置在spring的配置文件中,sessionFactory依然去配置它的dataSource属性,它甚至都不知道dataSource的改变。唯一不同的是在真正的dataSource与sessionFactory之间增加了一个MultiDataSource。

其次,实现简单,易于维护。这个方案虽然我说了这么多东西,其实都是分析,真正需要我们写的代码就只有MultiDataSource、SpObserver两个类。MultiDataSource类真正要写的只有getDataSource()和getDataSource(sp)两个方法,而SpObserver类更简单了。实现越简单,出错的可能就越小,维护性就越高。

最后,这个方案可以使单数据源与多数据源兼容。这个方案完全不影响BUS和DAO的编写。如果我们的项目在开始之初是单数据源的情况下开发,随着项目的进行,需要变更为多数据源,则只需要修改spring配置,并少量修改MVC层以便在请求中写入需要的数据源名,变更就完成了。如果我们的项目希望改回单数据源,则只需要简单修改配置文件。这样,为我们的项目将增加更多的弹性。

该方案的缺点

没有能够解决多用户访问单例“sessionFactory”时共享“dataSource”变量,导致产生争抢“dataSource”的结果,本质类似于操作系统中的“生产者消费者”问题。因此当多用户访问时,多数据源可能会导致系统性能下降的后果。

时间: 2024-10-10 20:17:13

Spring动态切换多数据源解决方案的相关文章

spring动态切换数据源(一)

介绍下spring数据源连接的源码类:| 1 spring动态切换连接池需要类AbstractRoutingDataSource的源码 2 /* 3 * Copyright 2002-2017 the original author or authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in comp

Spring动态配置多数据源

Spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性.而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据. 基本信息 1.Spring配置多数据源的方式和具体使用过程. 2.Spring对于多数据源,以数据库表为参照,大体上可以分成两大类情况: 一是,表级上的跨数据库.即,对于不同的数据库却有相同的表(表名和表结构完全相

spring boot mybatis多数据源解决方案

在我们的项目中不免会遇到需要在一个项目中使用多个数据源的问题,像我在得到一个任务将用户的聊天记录进行迁移的时候,就是用到了三个数据源,当时使用的AOP的编程方式根据访问的方法的不同进行动态的切换数据源,觉得性能不太好,先在又新用到了一种使用方式,觉得不错,记录下来. 介绍一下DEMO项目,使用的spring boot集成mybatis,mybatis查询数据库是基于注解形式查询的,目的查询两个数据库test1和test2的用户信息,并在控制台打印. 1.pom文件 1 <dependencies

spring动态设置多数据源

需求: 项目开发用的sping jdbctemplate, 之前数据源只有一个,现在数据源需要根据需求来进行变更, 也就是说 a用户------>需要访问A数据库服务器 b用户------>需要访问B数据库服务器 查询了资料,发现Spring提供了一个抽象类AbstractRoutingDataSource,为我们很方便的解决了这个问题. 实现: Spring配置文件applicationContext.xml(包含相关bean类的代码) <?xml version="1.0&

Spring动态多数据源实例Demo

最近由于咨询Spring如何配置多数据源的人很多,一一回答又比较麻烦,而且以前的博文中的配置也是有问题,因此特此重新发布一个Demo给大家. Demo中共有两个数据源,即Mysql和Oracle,并已经进行简单测试,动态切换数据源是没有问题的,希望借此Demo能帮助到大家. Demo下载地址: Spring动态切换多数据源Demo:http://download.csdn.net/download/wangpeng047/8419953 另外我给些说明,阐述下多数据源配置时的重点: 1. 注意事

基于Struts2 Spring ibatis Oracle10g架构 多数据源动态切换实例

一.概述 基于Spring动态配置多数据源,在大型的应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效的提高系统的水平伸缩性,而这样的解决方案就会补同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求以及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据. Spring配置多个数据源的方式和具体使用过程,Spring对于多数据源,以数据库表为参照,大体上可以分为两大类情况: 1.表级上的跨数据库,即对于不同的数据库却有不相同的表(表名和表结构完全

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

一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基本上没有什么问题,但唯一可能出现问题的就是在hibernate做添加操作生成主键策略的时候.因为我们都知道hibernate的数据库本地方言会针对不同的数据库采用不同的主键生成策略. 所以针对这一问题不得不采用自定义的主键生成策略,自己写一个主键生成器的表来维护主键生成方式或以及使用其他的方式来生成

springAOP实现基于注解的数据源动态切换

需求 代码实现读写数据库分离 武器 spring3.0以上版本 实现思路 1.继承org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource,自定义数据源路由. 2.实现数据源类型管理工具,诸如DBContextHolder,包含设置和读取当前数据源配置. 3.实现数据源切换的AOP. 4.自定义只读注解,诸如@ReadOnlyKey. 5.配置transactionManager,实现aop. 代码示例 1.自定义的

koala 多数据源动态切换

koala 特点:多数据源动态切换,数据源分组和负载均衡(轮询) 项目源码以及demo:https://github.com/zeq9069/koala 请大家关注一下哦!!哈哈! 最近,在开发项目的时候后,要用到多个数据源的动态切换,于是就开发了koala 这个小小得框架,koala支持多数据源的切换,数据源的分组和负载均衡(轮询)! 只需要将jar引入到你自己的项目中之后,然后进行简单配置就可以使用了!!使用起来 非常方便,该项目提供了三个核心的注解@ChangeTo,@DataSource