@Transactional导致dynamic-datasource-spring-boo。。。
环境:controller -->Aservice–>Bservice–>Bdao(A表⽰A数据源,B表⽰B数据源)
Aservcie使⽤Transactional注解
1、dynamic-datasource@DB切⾯是可以将数据源信息push到DynamicDataSourceContextHolder类的ThreadLocal<Deque> LOOKUP_KEY_HOLDER中
2、如果controller调⽤service,且controller -->Aservice–>Bservice–>Bdao(A表⽰A数据源,B表⽰B数据源),当且仅当Aservice使⽤@Transactional进⾏事物管理时,当controller -->Aservice,此时AbstractPlatformTransactionManager 类调⽤
doBegin(transaction, definition)⽅法,将执⾏TransactionSynchronizationManager的ThreadLocal<Map<Object, Object>> resources 加⼊A数据源
3、AbstractPlatformTransactionManager 类获取事物时候将会判断事物是否包含数据源,如果有则认为该事物已经存在,将进⾏事物的类型判断,如果是PROPAGATION_REQUIRES_NEW类型,将创建新事物,新事物将拥有新的数据源持有Holder,默认的话则继承事物
4、Aservice–>Bservcie虽然可以实现1中所述,但是Bservcie–>Bdao时,DataSourceUtils执⾏doGetConnection时候,将会执⾏Resource(dataSource)获取事物数据源A(源于2的结论),此时多数剧源形同虚设,失效,
⽅案:
1、Bservcie使⽤PROPAGATION_REQUIRES_NEW 类型事物,创建新事物 原因为上述3
2、使⽤Aservcie 的@Transactional替换成@DSTransactional注解即可,原因如下:
dynamic-datasource-spring-boot-starter启动时,进⾏DynamicDataSourceAutoConfiguration初始化,aop⾃定义事物,此时不⾛spring事物规则,将使⽤⾃定义事物,这个看起来很简单的事物规则,规避了复杂业务逻辑下的不便,代码如下:
@Slf4j
public class DynamicLocalTransactionAdvisor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation)throws Throwable {
if(!StringUtils.XID())){
return methodInvocation.proceed();
}
boolean state =true;
Object o;
String xid = UUID.randomUUID().toString();
TransactionContext.bind(xid);
try{
o = methodInvocation.proceed();
}catch(Exception e){
state =false;
springboot aop
throw e;
}finally{
}
return o;
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论