【多数据源切换】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]