【多数据源切换】dynamic-datasource多数据源(动态数据源)使用及案例;多数据源项目使用@DS切换数据库在事务中失效问题

多数据源(动态数据源)的需求:

  1. 不同的业务分多个数据库场景,例如一个程序负责n个省份的db操作
  2. 一主多从的读写分离的场景(一主多从可以使用MyBatis插件的方式实现)

dynamic-datasource

dynamic-datasource 是一个开源的 Spring Boot 多数据源启动器,提供了丰富的功能,包括数据源分组、敏感信息加密、独立初始化表结构等。

以下步骤在SpringBoot项目基础上实现:

1. 引入依赖:

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

2. 通过yml配置数据源:

默认数据源名为 master,可通过 spring.datasource.dynamic.primary 修改。

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候回抛出异常,不启动会使用默认数据源.
      datasource:
        master:
	      url: jdbc:mysql://xxxxa:3449/db1?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8&useSSL=false&&serverTimezone=Asia/Shanghai&&zeroDateTimeBehavior=convertToNull
          username: 用户名
          password: 密码
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave_1:
          url: jdbc:mysql://xxxxb:3449/db2?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8&useSSL=false&&serverTimezone=Asia/Shanghai&&zeroDateTimeBehavior=convertToNull
          username: 用户名
          password: 密码
          driver-class-name: com.mysql.cj.jdbc.Driver
       

3. 使用 @DS 切换数据源:

使用 @DS 注解来指定需要切换到的数据源,DS内部填写的值就是yml里面配置的key。

service层里面在想要切换数据源的方法上加上@DS注解就行了,也可以加在整个service层上,方法上的注解优先于类上注解

注解结果
没有@DS默认数据源
@DS(“dsName”)dsName可以为组名也可以为具体某个库的名称;数据源名称即yml里面配置的key

本案例读取master数据库中的数据,写入到slave_1数据库的新表中。

实体类上添加注解@DS("slave_1")指明当前类所使用的数据库。

@Data
@Accessors(chain = true)
@TableName("T_STUDENT")
@ApiModel(value="T_STUDENT", description="学生表")
@DS("slave_1")
public class StudentVerified {

    @ApiModelProperty(value = "主键")
    @TableField("id")
    private Long id;

    @ApiModelProperty(value = "姓名")
    @TableField("username")
    private String username;

    @ApiModelProperty(value = "身份证号")
    @TableField("idCardNumber")
    private String idCardNumber;

}

如果要使用mybatisplus方法,需直接在Service类上直接添加注解

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@DS("slave_1")
public class StudentVerifiedServiceImpl extends ServiceImpl<StudentVerifiedMapper, StudentVerified> {

}
public interface StudentVerifiedMapper extends BaseMapper<StudentVerified> {
}

使用master主数据源(​​不需做任何操作​​,和之前单数据库一样)

启动项目时可以看到相关日志输出

在这里插入图片描述

4. 在测试方法中实现逻辑

@SpringBootTest
public class Multidata {
    @Autowired
    private IBusCertificationService certificationService;

    @Autowired
    private StudentVerifiedServiceImpl studentVerifiedService;

    /**
     * 将master的实名认证数据导入到slave的Student表中
     */
    @Test
    void mult(){
        List<BusCertification> userCertification = certificationService.list();
        List<StudentVerified> studentVerifiedList = new ArrayList<>();
        for (BusCertification busCertification : userCertification) {
            StudentVerified studentVerified = new StudentVerified();
            studentVerified.setId(busCertification.getId());
            studentVerified.setUsername(busCertification.getUsername());
            studentVerified.setIdCardNumber(busCertification.getIdCardNumber());
            studentVerifiedList.add(studentVerified);
        }
        //此处调用方法时会根据注解切换到slave数据库中
        studentVerifiedService.saveBatch(studentVerifiedList);
    }
    
}

多数据源项目使用@DS切换数据库在事务中失效问题

如果在同一个方法内分别操作了主从库,并且方法上有事务注解,很有可能会导致从库查询失败。因为加入@Transitional注解后,数据源切换会失效,只会操作主库。

此时需将方法上注解修改为

@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void applyCheck(ApplyCheckPO po) {
	//······
	//调用从库方法
}

同时,最好将从库相关操作放置从库serviceImpl的方法中,再由外层调用该方法并try…catch环绕,同时从库该方法上也加上注解

@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
`dynamic-datasource` 是一个多数据源切换的解决方案,特别适用于Spring Boot项目中需要连接多个数据库的情况。为了实现动态数据源的选择,在代码里我们通常会用到注解如 `@DS` 来指定当前操作应该使用哪一个数据源。 如果你遇到的问题是标记了 `@DS` 注解之后它并没有按照预期工作,那么这里有一些检查点可以帮助解决问题: ### 1. 引入依赖 首先确认你已经在项目的pom.xml文件中引入了正确的依赖库,例如: ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>x.x.x</version><!-- 根据实际情况选择版本 --> </dependency> ``` ### 2. 配置数据源信息 确保你的application.yml或properties配置文件中有正确设置所有你需要的数据源,并启用了主从模式或多数据源特性: ```yaml spring: datasource: dynamic: primary: master # 设置默认使用数据源名称,默认取第一个dataSource作为primary strict: false # 是否开启严格的多数据源模式,建议关闭 ds-master: # 主库配置 url: jdbc:mysql://localhost:3306/dbname?useSSL=false&serverTimezone=UTC username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver ds-slave: # 从库配置示例 url: jdbc:mysql://otherhost:3306/samedbname?useSSL=false&serverTimezone=UTC username: slave_user password: slave_pwd driver-class-name: com.mysql.cj.jdbc.Driver ``` 请注意这里的ds-master 和 ds-slave只是例子,你可以根据实际需求命名更多不同的数据源。 ### 3. 检查 `@DS` 使用位置 确保你在合适的地方添加了 `@DS("yourDataSourceName")` 这样的注解。一般来说这个注解可以放在service层的方法上、controller层方法之上或是Repository/DAO接口级别等,这取决于你想控制粒度大小及业务逻辑的具体情况。 如果上述步骤都已经完成还是不起作用的话,请考虑以下几个方面进一步排查原因: - 确保你的实体类和服务类都已经被Spring管理并且能够正常注入; - 查看是否有关于AOP(面向切面编程)方面的配置影响到了 `@DS` 的解析过程; - 如果是在事务环境中出现问题,则需注意@Transactional和 @DS 的顺序问题以及传播行为对数据源的影响; 最后但同样重要的是查看日志输出内容,尤其是错误堆栈跟踪信息可能会提供关于为什么 `@DS` 没有按预期工作的线索。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值