老婆出轨 发表于 2025-1-7 20:30:16

【多数据源切换】dynamic-datasource多数据源(动态数据源)使用及案例;多

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

[*]不同的业务分多个数据库场景,比方一个程序负责n个省份的db操作
[*]一主多从的读写分离的场景(一主多从可以使用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主数据源(​​不需做任何操作​​,和之前单数据库一样)
启动项目时可以看到相关日志输出
https://i-blog.csdnimg.cn/direct/bbc1166820df4f5ca4c3c05b0b65dd4d.png
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)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【多数据源切换】dynamic-datasource多数据源(动态数据源)使用及案例;多