为什么存在数据源切换和食物时效问题?
由于业务数据来源不同 需要配置多个数据源来进行数据的查询 编辑等操作 这一切换业务对数据的一致性要求很高那就要保证ACID啦 也就是数据的有效性 要么是成功的 要么是失败的。
数据源切换采用mybatisplus支持
多数据源配置:oracle和mysql的数据类型
spring:
datasource:
dynamic:
primary: master #设置默认的数据源或者数据源组,默认值即为master
datasource:
master:
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://10.20.204.130:3306/user?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
coloan:
username: root
password: root
driver-class-name: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@10.20.201.173:1521:rthhhhhdb
由于是公司业务 故大致做一些特殊类名称的改改写
1:方法的入口
@RestController
public class testContorller {
@Autowired
testService testService;
@PostMapping("/queryBankInfoList")
public String queryBankInfoList(){
List<CoTodoTask> coTodoTasks = testService.queryBankInfoList();
return JSON.toJSONString(JSON.toJSONString(coTodoTasks));
}
}
service接口定义
public interface testService extends IService<CoTodoTask> {
List<Task> queryBankInfoList();
}
实现service的核心类
Service
@DS("coloan")
public class testServiceImpl extends ServiceImpl<TaskMapper, Task> implements testService {
@Autowired
UserService userService;
@Autowired
TaskMapper TaskMapper;
@Transactional(rollbackFor = Exception.class)
@Override
public List<Task> queryBankInfoList() {
// 用户表在MySQL
Result result = userService.userInfo(117);
QueryWrapper<Task> wrapper = new QueryWrapper<>();
wrapper.isNotNull("id");
// 任务表在Oracle中
List<Task> Tasks = TaskMapper.selectList(wrapper);
return Tasks;
}
}
默认主数据原 这里可以不用注解指定 因为配置文件默认的主数据原就是master 这里我加上了
@Service
@DS("master")
public class UserServiceImpl implements UserService {
@Override
public Result userInfo(Integer userId) {
User user = userMapper.selectUser(userId, null);
return new Result().setData(userVO);
}
}
运行调试 发现一下问题
Error querying database. Cause: java.sql.SQLSyntaxErrorException: ORA-00942: 表或视图不存在
注意观察信息
userService的数据库应该是master,但是却是coloan的,导致代码报500,也就是说@DS切换数据源没有起作用
初步结论
多数据源失效,然后去掉事务发现切换正常 在于这样的切换失去了事务控制的行为。
通过下面的方式解决
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
@Override
public List<CoTodoTask> queryBankInfoList() {
...
}
通过上述的修改 数据源能正常的切换 并且可控事务
2:什么是事务的传播特性
当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
事务的传播行为可以由传播属性指定。Spring定义了7种类传播行为。
演示事务的传播特性
ps:这里借用一下我之前看到的一篇关于事务传播特性特别棒的几张图片。
1:大小事务传播特性都是REQUIRED
@Transactional(propagation = Propagation.REQUIRED)
public void multiTransaction() {}
@Transactional(propagation = Propagation.REQUIRED)
public void updateBook() {}
@Transactional(propagation=Propagation.REQUIRED)
public void updateUser() {}
传播流程:
大小事务传播特性都是REQUIRES_NEW
传播流程:
3:大事务是REQUIRED,小1REQUIRED,小2REQUIRES_NEW
传播流程:
总结:
事务会导致多数据源失效,这个大家一定要记清
一定要明白事务的传播特性,开发中其实常用的就只有REQUIRED和REQUIRES_NEW,大家只要把这两个搞明白,就能应对绝大数的问题。
以上是mybatis-plus之数据源切换事务失效问题 关注老哥带你上高速 。。。。。。。。。