@DS(“slave“) 多数据源兼容事务问题解决方案

项目场景:

SpringBoot项目中用到多数据源,在方法上又必须加事务处理,此时可以对使用了@DS的方法或类添加@Transactional并添加事务隔离级别


问题描述

多数据源场景下 单纯只添加 @Transactional 会导致数据源无法切换,使用的是之前的数据源

例如 transToZfjd 方法调用 insertAndUpdateToZf

@DS(“slave“) 多数据源兼容事务问题解决方案_第1张图片

同时候需要切换数据源与开启事务

@DS(“slave“) 多数据源兼容事务问题解决方案_第2张图片
添加 @Transactional() 时,数据源不会被切换使用的还是 transToZfjd方法的数据源

原因分析:

因为SPRING在开启事务的同时,会去数据库连接池拿数据库连接。如果仅在主方法上添加@TRANSACTIONAL,那么,TRANSACTIONINTERCEPTOR会使用 SPRING DATASOURCETRANSACTIONMANAGER创建事务,并将事务信息(获取数据源CONNECTION连接,此时获取到的数据源是默认配置的BASE数据源信息)连接信息,通过 THREADLOCAL 绑定在当前线程。

此时当前线程事务绑定的连接信息是BASE数据源,当我们在内层切换数据源方法上使用@DS切换数据源,并没有重新开启新事务,没有改变当前线程事务的连接信息,仅仅是做了一次拦截,改变了DATASOURCEHOLDER的栈顶DATASOURCE,对于整个事务的连接是没有影响的,所以会产生数据源没有切换的问题。

所以这里的解决办法是,将保证住方法操作数据完整性的事务,拆解成两个事务,在切换数据源方法类上,除了添加切换数据源的注解@DS(“DB2”),再添加@TRANSACTIONAL(PROPAGATION = PROPAGATION.REQUIRES_NEW, ROLLBACKFOR = EXCEPTION.CLASS),新建开一个事务,获取新数据源CONNECTION连接。


解决方案:

用到多数据源的方法不能使用事务,如果主方法必须使用事务,那么slave数据源方法上或类上需要添加 下面注解。

@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)

其他

在使用@DS注解时,有如下注意事项:

  • 不能使用事务,否则数据源不会切换,使用的还是第一次加载的数据源;

  • 第一次加载数据源之后,第二次、第三次…操作其它数据源,如果数据源不存在,使用的还是第一次加载的数据源;

  • 数据源名称不要包含下划线,否则不能切换。

原文

你可能感兴趣的:(Spring,错误记录,java,spring,spring,boot)