前两篇文章已经介绍了动态数据源的具体实现过程,在经过一段时间的使用后,发现了两个比较严重的问题,在这里进行补充说明。
事务执行失败时没有切回默认数据源
@Transactional
注解的方法意味着使用数据库事务执行方法中的 sql 操作,默认情况下当方法抛出不受检查异常时,事务会进行回滚,我所实现的动态数据源方案通过 AOP 和注解的方式切换数据源, @Transactional
方法执行前切换目标数据源,执行完成后切换回默认数据源。
但当方法抛出不受检查异常时,AOP 方法无法执行到切回默认数据源的语句,因此在下次使用数据源时就会出错,期望使用的是默认数据源,然而并不是。
解决方法是把切回默认数据源的语句放在 finally(try {} funally {}
) 块中执行。
@Around(value = "@annotation(dataSource)")
public Object changeDataSource(ProceedingJoinPoint point, DataSource dataSource) throws Throwable {
DsKey dsKey = dataSource.dsKey();
if (!DynamicDataSource.contains(dsKey)) {
return null;
}
DynamicDataSource.setDataSourceKey(dsKey);
try {
return point.proceed();
} finally { // 兼顾事务回滚的情况
DynamicDataSource.clearDataSourceType(); // 恢复默认
}
}
@Transactional
注解的方法中使用多个数据源
此时事务只会对前一个数据源生效,这里就涉及到分布式事务的知识,详细的分析之后再进行总结,
可先参考以下文章:
网友评论