springboot使用dynamic做多数据源配置全过程

 更新时间:2025年12月01日 09:53:17   作者:SingleCase  
文章介绍了如何使用dynamic依赖实现多数据源配置,并解决多数据源失效问题,通过配置yml文件、使用@DS注解指定数据源以及合理使用事务传播机制,成功解决了项目中的多数据源问题

最近项目需求,需要用到多数据源配置,经过一番学习完成需求功能开发,本文介绍一下我用到的dynamic做动态数据源配置。

1. 依赖导入

这里用到dynamic依赖,和对应的数据源(mysql,oracle等)依赖。以下是dynamic依赖:

	<dependency>
		<groupId>com.baomidou</groupId>
		<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
		<version>3.5.0</version>
	</dependency>

2.yml配置

yml配置主要是将多个数据源分别配置,并指定默认数据源,具体yml配置参考如下:

spring:
  datasource:
    dynamic:
      primary: kingbase # 设置主库为kingbase
      strict: false # 严格匹配数据源,默认false,当为true时,未匹配到指定数据源时抛异常,false未匹配到指定数据源会使用默认数据源
      datasource:
        kingbase: # 这的kingbase是自定义的数据源名称,不是指数据库的类型
          url: jdbc:kingbase8://${DATABASE_HOST:127.0.0.1}:${DATABASE_PORT:54323}/${DATABASE_DBNAME:kingbase}?serverTimezone=GTM%2B8
          username: ${DATABASE_USERNAME:SYSTEM}
          password: ${DATABASE_PASSWORD:12345}
          driverClassName: com.kingbase8.Driver
          type: com.alibaba.druid.pool.DruidDataSource
        mysql:
          url: jdbc:mysql://${DATABASE_HOST:127.0.0.1}:${DATABASE_PORT:3306}/${DATABASE_DBNAME:mysql}?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
          username: ${DATABASE_USERNAME:root}
          password: ${DATABASE_PASSWORD:1234}
          driverClassName: com.mysql.cj.jdbc.Driver
          type: com.alibaba.druid.pool.DruidDataSource

使用时,只需要在对应的mapper上,使用注解@DS(“mysql”),指定当前mapper数据源为mysql数据源

3.多数据源失效问题

常见的多数据源失效问题可以从配置方面去排查,例如,yml配置,DS指定数据源配置等方面。

这里我介绍一下我在使用过程中遇到的多数据源失效问题。

问题情境

我在同一个方法中,先调用了主数据源(kingbase)中的某个表数据,然后再调用了从数据源(mysql)中的数据,然后执行下面业务逻辑,我这后面涉及到对数据库的写操作,我在方法上用了@Transactional注解管理事务,然后我发现,调用主数据源的时候,数据获取正常,调用从数据源的时候,报错没有xx表,查看报错信息为kingbaseSQLException,就知道了调用的主数据源数据,多数据源失效了。于是开始排查

问题排查

(1) 配置问题

首先查看是否是配置原因,检查yml配置和mapper配置是否正确,然后我写了个测试接口,测试多数据源是否有效,测试接口直接调用获取从数据源数据,获取正确,不是这个原因。

(2)方法代理问题

我将获取数据的代码单独封装方法,然后通过自动注入service,用注入的service调用方法获取对应所需的数据,仍然发现此问题,不是这个原因。

(3)事务管理问题

这里我查询了相关资料,得知在方法上添加事务,事务只会对一个数据源进行事务管理。其实说得通俗易懂一点就是,一个数据库的事务管不住另一个数据库的事务。

ok,问题找到现在开始解决问题。

问题解决

根据我这问题产生原因,思路很简单,对每个数据源数据获取单独使用事务管理,这里可以了解一下spring的事务传播机制,默认传播机制为Propagation.REQUIRED(如果当前没有事务,就新建一个事务,如果已

经存在一个事务中,加入到这个事务中),所以在我前面使用方法代理排查问题的时候,还是不行,因为使用的默认传播机制。

这里补充一下事务传播机制:

PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。- 默认
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作

基于上面提到的事务传播机制,我这将对数据库的操作封装成独立方法,然后我使用PROPAGATION_REQUIRES_NEW传播机制,新建事务,使用方式@Transactional(propagation = Propagation.REQUIRES_NEW)。然后再次测试功能,发现报另一个错了,这就说明这个多数据源失效问题,已经解决。我这的另一个错产生原因主要是项目中使用到了Neo4j,而这个事务只支持默认事务,所以报错。

问题解决其他思路

我这因为Neo4j不适合使用多个事务进行事务管理。所以我这将代码逻辑进行了处理,我将接口的入口方法,单独封装方法,然后将数据进行业务逻辑处理后,统一添加到数据库和Neo4j中,这里我将数据添加逻辑单独封装方法进行处理,最后问题解决,功能测试通过。

其实也可以在代码中不使用@Transcational注解,可以在代码块中手动开启提交回滚事务,也可以达到效果。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • MyBatis拦截器的原理与使用

    MyBatis拦截器的原理与使用

    本文全面的讲解了MyBatis拦截器的作用原理及使用方法,拦截器的使用可以提升开发效率,学习MyBatis的朋友不妨了解下本文
    2021-06-06
  • java实现哈夫曼压缩的实例

    java实现哈夫曼压缩的实例

    这篇文章主要介绍了java实现哈夫曼压缩的实例的相关资料,需要的朋友可以参考下
    2017-07-07
  • json如何解析混合数组对象到实体类的list集合里去

    json如何解析混合数组对象到实体类的list集合里去

    这篇文章主要介绍了json解析混合数组对象到实体类的list集合里去的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • SpringBoot自定义内容协商的实现

    SpringBoot自定义内容协商的实现

    在Spring Boot中,内容协商是一种机制,它允许服务器根据客户端的请求选择返回不同的表示形式,本文就来详细的介绍一下SpringBoot自定义内容协商的实现,感兴趣的可以了解一下
    2024-09-09
  • Java获取当前系统事件System.currentTimeMillis()方法

    Java获取当前系统事件System.currentTimeMillis()方法

    下面小编就为大家带来一篇Java获取当前系统事件System.currentTimeMillis()方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Java中Lambda表达式的使用详解

    Java中Lambda表达式的使用详解

    Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用 Lambda 表达式可以使代码变的更加简洁紧凑
    2021-09-09
  • java如何判断时间段是否交叉重叠

    java如何判断时间段是否交叉重叠

    这篇文章主要介绍了java如何判断时间段是否交叉重叠问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • springboot启动不加载bootstrap.yml文件的问题

    springboot启动不加载bootstrap.yml文件的问题

    这篇文章主要介绍了springboot启动不加载bootstrap.yml文件的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • mybatis QueryWrapper的条件构造之apply、last、select解析

    mybatis QueryWrapper的条件构造之apply、last、select解析

    这篇文章主要介绍了mybatis QueryWrapper的条件构造之apply、last、select,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Java使用MessageFormat应注意的问题

    Java使用MessageFormat应注意的问题

    这篇文章主要介绍了Java使用MessageFormat应注意的问题,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-06-06

最新评论