搜索
首页Javajava教程Spring实现动态切换多数据源的解决方案

前言

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

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

实现

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

一、动态配置多数据源

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

/**
 * 动态配置多数据源
 * 数据源的名称常量类
 * @author LONGHUI_LUO
 *
 */
public class DataSourceConst {
 public static final String TEST="test";
 public static final String USER="User";
}

   


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

/**
 * 获得和设置上下文环境 主要负责改变上下文数据源的名称
 *
 * @author LONGHUI_LUO
 *
 */
public class DataSourceContextHolder {
 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();
 }
  
}

   


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

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

   


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

  <!-- 数据源相同的内容 -->
<bean
  id="parentDataSource"
  class="org.apache.commons.dbcp.BasicDataSource"
  destroy-method="close">
  <property
   name="driverClassName"
   value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
  <property name="username" value="sa" />
  <property name="password" value="net2com" />
</bean>
<!-- start以下配置各个数据源的特性 -->
<bean parent="parentDataSource" id="testDataSource">
  <propertynamepropertyname="url" value="jdbc:sqlserver://localhost:1433;databaseName=test" />
</bean>
<bean parent="parentDataSource" id="UserDataSource">
   <property
   name="url"
   value="jdbc:sqlserver://localhost:1433;databaseName=User" />
</bean>
<!-- end 配置各个数据源的特性 -->

   


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

<bean class="com.xxxx.datasouce.DynamicDataSource" id="dataSource">
 <property name="targetDataSources">
  <map key-type="java.lang.String">
   <entry value-ref="testDataSource" key="test"></entry>
   <entry value-ref="UserDataSource" key="User"></entry>
  </map>
 </property>
 <property name="defaultTargetDataSource" ref="testDataSource" ></property>
</bean>

   


在这个配置中第一个property属性配置目标数据源,ee00b946da06d7503cfd8c154bb1f49b中的key-type必须要和静态键值对照类DataSourceConst中的值的类型相 同;64432118af1b91af4357e86727840340中key的值必须要和静态键值对照类中的值相同,如果有多个值,可以配置多个60a9697022de2b8c5f7c1cff80ba8e28标签。第二个property属性配置默认的数据源。

动态切换是数据源

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实现动态切换多数据源的解决方案相关文章请关注PHP中文网!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
是否有任何威胁或增强Java平台独立性的新兴技术?是否有任何威胁或增强Java平台独立性的新兴技术?Apr 24, 2025 am 12:11 AM

新兴技术对Java的平台独立性既有威胁也有增强。1)云计算和容器化技术如Docker增强了Java的平台独立性,但需要优化以适应不同云环境。2)WebAssembly通过GraalVM编译Java代码,扩展了其平台独立性,但需与其他语言竞争性能。

JVM的实现是什么,它们都提供了相同的平台独立性?JVM的实现是什么,它们都提供了相同的平台独立性?Apr 24, 2025 am 12:10 AM

不同JVM实现都能提供平台独立性,但表现略有不同。1.OracleHotSpot和OpenJDKJVM在平台独立性上表现相似,但OpenJDK可能需额外配置。2.IBMJ9JVM在特定操作系统上表现优化。3.GraalVM支持多语言,需额外配置。4.AzulZingJVM需特定平台调整。

平台独立性如何降低发展成本和时间?平台独立性如何降低发展成本和时间?Apr 24, 2025 am 12:08 AM

平台独立性通过在多种操作系统上运行同一套代码,降低开发成本和缩短开发时间。具体表现为:1.减少开发时间,只需维护一套代码;2.降低维护成本,统一测试流程;3.快速迭代和团队协作,简化部署过程。

Java的平台独立性如何促进代码重用?Java的平台独立性如何促进代码重用?Apr 24, 2025 am 12:05 AM

Java'splatformindependencefacilitatescodereusebyallowingbytecodetorunonanyplatformwithaJVM.1)Developerscanwritecodeonceforconsistentbehavioracrossplatforms.2)Maintenanceisreducedascodedoesn'tneedrewriting.3)Librariesandframeworkscanbesharedacrossproj

您如何在Java应用程序中对平台特定问题进行故障排除?您如何在Java应用程序中对平台特定问题进行故障排除?Apr 24, 2025 am 12:04 AM

要解决Java应用程序中的平台特定问题,可以采取以下步骤:1.使用Java的System类查看系统属性以了解运行环境。2.利用File类或java.nio.file包处理文件路径。3.根据操作系统条件加载本地库。4.使用VisualVM或JProfiler优化跨平台性能。5.通过Docker容器化确保测试环境与生产环境一致。6.利用GitHubActions在多个平台上进行自动化测试。这些方法有助于有效地解决Java应用程序中的平台特定问题。

JVM中的类加载程序子系统如何促进平台独立性?JVM中的类加载程序子系统如何促进平台独立性?Apr 23, 2025 am 12:14 AM

类加载器通过统一的类文件格式、动态加载、双亲委派模型和平台无关的字节码,确保Java程序在不同平台上的一致性和兼容性,实现平台独立性。

Java编译器会产生特定于平台的代码吗?解释。Java编译器会产生特定于平台的代码吗?解释。Apr 23, 2025 am 12:09 AM

Java编译器生成的代码是平台无关的,但最终执行的代码是平台特定的。1.Java源代码编译成平台无关的字节码。2.JVM将字节码转换为特定平台的机器码,确保跨平台运行但性能可能不同。

JVM如何处理不同操作系统的多线程?JVM如何处理不同操作系统的多线程?Apr 23, 2025 am 12:07 AM

多线程在现代编程中重要,因为它能提高程序的响应性和资源利用率,并处理复杂的并发任务。JVM通过线程映射、调度机制和同步锁机制,在不同操作系统上确保多线程的一致性和高效性。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。