`
youyu4
  • 浏览: 435919 次
社区版块
存档分类
最新评论

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.     // 设置数据源类型  
  11.     public static void setDataSourceType(String dataSourceType) {  
  12.         contextHolder.set(dataSourceType);  
  13.     }  
  14.   
  15.     // 获取数据源类型  
  16.     public static String getDataSourceType() {  
  17.         return (String) contextHolder.get();  
  18.     }  
  19.   
  20.     // 清除数据源类型  
  21.     public static void clearDataSourceType() {  
  22.         contextHolder.remove();  
  23.     }  
  24.   
  25. }  


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.   
  9.  protected Object determineCurrentLookupKey() {  
  10.   // 在进行DAO操作前,通过上下文环境变量,获得数据源的类型  
  11.   return DataSourceContextHolder.getDataSourceType();  
  12.  }  
  13.   
  14. }  


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”的结果,本质类似于操作系统中的“生产者消费者”问题。因此当多用户访问时,多数据源可能会导致系统性能下降的后果。
 
 
简单实用的方法:
分享到:
评论

相关推荐

    Spring+SpringMvc+MybatisPlus+Aop(自定义注解)动态切换数据源

    本项目“Spring+SpringMvc+MybatisPlus+Aop(自定义注解)动态切换数据源”正是针对这一需求提供的一种解决方案。下面将详细介绍这个项目中的关键技术点和实现原理。 首先,Spring框架是Java企业级应用开发的核心...

    spring多数据源动态切换方案

    总结,Spring多数据源动态切换方案主要涉及创建多个数据源、使用AbstractRoutingDataSource进行动态路由、配置事务管理和在代码中切换数据源。通过这种方式,我们可以灵活地处理复杂的数据源切换场景,适应不同业务...

    Spring多数据源解决方案

    Spring多数据源解决方案是针对大型应用中数据分片和分布式数据库管理的需求而设计的一种策略。在这样的场景下,为了提高系统的可扩展性和性能,数据通常会被分散到多个数据库实例上。这种架构如图1所示,每个数据库...

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

    Spring 实现动态切换多数据源的解决方案是针对大型应用程序中数据切分的需求,通过使用多个数据库实例提升系统的可扩展性。在这样的架构中,程序需要根据请求和系统状态动态选择数据存储和读取的数据库。Spring 从 2...

    Spring 动态切换数据源

    在上述描述中,动态切换数据源的解决方案主要基于Spring提供的`AbstractRoutingDataSource`抽象类。这个类允许我们创建自定义的数据源,它可以根据特定的规则(如当前请求上下文、用户类型或其他业务逻辑)来决定...

    spring动态数据源+mybatis分库分表

    "spring动态数据源+mybatis分库分表"是一个针对大型数据库场景的解决方案,它利用Spring框架的动态数据源功能和MyBatis的SQL映射能力,实现数据库的透明化分片。以下是这个主题的详细知识点: 1. **Spring动态数据...

    spring boot mybatis多数据源最简解决方案

    总的来说,Spring Boot和MyBatis的多数据源解决方案为开发者提供了一种灵活、可扩展的方式来管理和操作多个数据库,满足了复杂业务场景下的需求。通过合理的配置和设计,可以有效提升系统的稳定性和性能。

    springboot连接池、动态配置多数据源连接池,特别适合大数据部门、数据中台服务的多数据源连接池.zip

    综上所述,"spring-boot-easy-connection-pool-master"项目提供了一种实用的解决方案,它结合了Spring Boot的便利性和多数据源的灵活性,为大数据环境下的数据访问和管理带来了极大的便利。通过深入学习和实践该项目...

    spring框架多数据源切换问题的解决

    首先,这个方案完全是在spring的框架下解决的,数据源依然配置在spring的配置文件中,sessionFactory依然去配置它的dataSource属性,它甚至都不知道dataSource的改变。 其次,实现简单,易于维护。这个方案虽然我说...

    springboot实现多数据源而且加上事务不会使aop切换数据源失效

    为了实现AOP动态切换数据源,我们可以创建一个自定义的注解,如`@UseSecondaryDataSource`,并编写对应的切面来处理数据源切换: ```java @Aspect @Component public class DataSourceAspect { @Autowired ...

    基于Spring多数据源实例

    在IT行业中,数据库是系统的核心组成部分,特别是...通过理解上述步骤和原理,开发者可以更好地设计和实施适用于各种业务场景的多数据源解决方案。在实际操作中,应根据项目需求灵活调整,以达到最佳的性能和可维护性。

    SpringBoot+Atomikos分布式事务及多数据源动态切换,两种demo

    总的来说,Spring Boot与Atomikos的结合提供了强大的分布式事务解决方案,而动态数据源切换则增强了系统的灵活性,适应了复杂的企业级应用场景。开发者需要理解这些技术背后的原理,并通过实践来熟练掌握它们。

    Spring动态切换datasource实现mysql多住多从

    Spring框架提供了强大的数据源管理能力,我们可以利用它来实现动态切换数据源。具体步骤如下: 1. **配置数据源**:首先,需要配置多个数据源。在Spring配置文件中,可以定义多个DataSource bean,每个bean代表一个...

    mybatis spring 多数据源

    标签中的"源码"可能指的是理解MyBatis和Spring框架内部如何处理多数据源的关键代码,这有助于我们更深入地定制和优化解决方案。"工具"可能是指像Druid、HikariCP这样的数据库连接池,它们在多数据源配置中起着至关...

    springboot多数据源,DruidDataSource多数据源切换,不重启项目,修改数据库名解决方案

    项目背景: 1. Springboot项目 2. 一个主数据源,数据名称库不变。 3.... 明天2号,是db_02。...4.不重启项目切换数据源。 5.项目介绍: https://blog.csdn.net/qq_38105536/article/details/122296977

    springboot整合rabbitMq和多数据源动态切换和跨域访问和gradle加maven和shiro安全框架和lombok自动getset生成

    标题中的“springboot整合rabbitMq和多数据源动态切换和跨域访问和gradle加maven和shiro安全框架和lombok自动getset生成”表明这是一个关于Spring Boot集成多个技术的项目。以下是对这些技术及其整合的详细解释: 1...

    spring boot mybatis多数据源解决方案过程解析

    Spring Boot MyBatis 多数据源解决方案过程解析 在实际项目中,我们经常会遇到需要在一个项目中使用多个数据源的问题。例如,在迁移用户的聊天记录时,我们需要使用三个数据源。这时,我们可以使用 Spring Boot 和 ...

    多数据源切换

    多数据源切换的核心在于动态选择和切换数据源,这通常通过配置或编程方式实现。在Java中,我们可以利用Spring框架的强大功能来轻松实现这一目标。Spring提供了多种数据源切换的解决方案,如...

    如何在spring框架中解决多数据源的问题

    - **装饰者模式的应用**:使用装饰者模式来包装原有的数据源,从而实现在不修改原始数据源的基础上增加新的功能,如动态切换数据源的能力。 ##### 2. 技术实现 - **单例模式的问题**:在Spring中,通常情况下注册...

    Springboot整合Druid与Mybatis的多数据源切换

    本教程将详细介绍如何在Spring Boot项目中整合Druid数据源池与Mybatis,实现多数据源切换的功能,并提供一个亲测可用的解决方案。 首先,让我们了解Spring Boot、Druid和Mybatis这三大组件的基础知识: **Spring ...

Global site tag (gtag.js) - Google Analytics