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

打印 上一主题 下一主题

主题 976|帖子 976|积分 2928

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

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

dynamic-datasource 是一个开源的 Spring Boot 多数据源启动器,提供了丰富的功能,包罗数据源分组、敏感信息加密、独立初始化表结构等。
以下步骤在SpringBoot项目基础上实现:
1. 引入依靠:

  1.         <dependency>
  2.             <groupId>com.baomidou</groupId>
  3.             <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  4.             <version>3.1.0</version>
  5.         </dependency>
复制代码
2. 通过yml配置数据源:

默认数据源名为 master,可通过 spring.datasource.dynamic.primary 修改。
  1. spring:
  2.   datasource:
  3.     dynamic:
  4.       primary: master #设置默认的数据源或者数据源组,默认值即为master
  5.       strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候回抛出异常,不启动会使用默认数据源.
  6.       datasource:
  7.         master:
  8.               url: jdbc:mysql://xxxxa:3449/db1?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8&useSSL=false&&serverTimezone=Asia/Shanghai&&zeroDateTimeBehavior=convertToNull
  9.           username: 用户名
  10.           password: 密码
  11.           driver-class-name: com.mysql.cj.jdbc.Driver
  12.         slave_1:
  13.           url: jdbc:mysql://xxxxb:3449/db2?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8&useSSL=false&&serverTimezone=Asia/Shanghai&&zeroDateTimeBehavior=convertToNull
  14.           username: 用户名
  15.           password: 密码
  16.           driver-class-name: com.mysql.cj.jdbc.Driver
  17.       
复制代码
3. 使用 @DS 切换数据源:

使用 @DS 注解来指定必要切换到的数据源,DS内部填写的值就是yml内里配置的key。
service层内里在想要切换数据源的方法上加上@DS注解就行了,也可以加在整个service层上,方法上的注解优先于类上注解
注解结果没有@DS默认数据源@DS(“dsName”)dsName可以为组名也可以为具体某个库的名称;数据源名称即yml内里配置的key   本案例读取master数据库中的数据,写入到slave_1数据库的新表中。
  实体类上添加注解@DS("slave_1")指明当前类所使用的数据库。
  1. @Data
  2. @Accessors(chain = true)
  3. @TableName("T_STUDENT")
  4. @ApiModel(value="T_STUDENT", description="学生表")
  5. @DS("slave_1")
  6. public class StudentVerified {
  7.     @ApiModelProperty(value = "主键")
  8.     @TableField("id")
  9.     private Long id;
  10.     @ApiModelProperty(value = "姓名")
  11.     @TableField("username")
  12.     private String username;
  13.     @ApiModelProperty(value = "身份证号")
  14.     @TableField("idCardNumber")
  15.     private String idCardNumber;
  16. }
复制代码
假如要使用mybatisplus方法,需直接在Service类上直接添加注解
  1. @Service
  2. @RequiredArgsConstructor(onConstructor = @__(@Autowired))
  3. @DS("slave_1")
  4. public class StudentVerifiedServiceImpl extends ServiceImpl<StudentVerifiedMapper, StudentVerified> {
  5. }
复制代码
  1. public interface StudentVerifiedMapper extends BaseMapper<StudentVerified> {
  2. }
复制代码
  使用master主数据源(​​不需做任何操作​​,和之前单数据库一样)
  启动项目时可以看到相关日志输出

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

  1. @SpringBootTest
  2. public class Multidata {
  3.     @Autowired
  4.     private IBusCertificationService certificationService;
  5.     @Autowired
  6.     private StudentVerifiedServiceImpl studentVerifiedService;
  7.     /**
  8.      * 将master的实名认证数据导入到slave的Student表中
  9.      */
  10.     @Test
  11.     void mult(){
  12.         List<BusCertification> userCertification = certificationService.list();
  13.         List<StudentVerified> studentVerifiedList = new ArrayList<>();
  14.         for (BusCertification busCertification : userCertification) {
  15.             StudentVerified studentVerified = new StudentVerified();
  16.             studentVerified.setId(busCertification.getId());
  17.             studentVerified.setUsername(busCertification.getUsername());
  18.             studentVerified.setIdCardNumber(busCertification.getIdCardNumber());
  19.             studentVerifiedList.add(studentVerified);
  20.         }
  21.         //此处调用方法时会根据注解切换到slave数据库中
  22.         studentVerifiedService.saveBatch(studentVerifiedList);
  23.     }
  24.    
  25. }
复制代码
多数据源项目使用@DS切换数据库在事务中失效问题

假如在同一个方法内分别操作了主从库,而且方法上有事务注解,很有可能会导致从库查询失败。因为加入@Transitional注解后,数据源切换会失效,只会操作主库。
此时需将方法上注解修改为
  1. @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
  2. public void applyCheck(ApplyCheckPO po) {
  3.         //······
  4.         //调用从库方法
  5. }
复制代码
同时,最好将从库相关操作放置从库serviceImpl的方法中,再由外层调用该方法并try…catch环绕,同时从库该方法上也加上注解
  1. @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

老婆出轨

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表