码迷,mamicode.com
首页 > 其他好文 > 详细

Transaction事务注解和DynamicDataSource动态数据源切换问题解决

时间:2014-05-30 05:56:49      阅读:2332      评论:0      收藏:0      [点我收藏+]

标签:c   style   class   blog   code   java   

问题描述: 写主库开事务的情况下会导致时不时的将更新/插入操作写入到从库上, 导致mysqlException

 

问题原因: jetty的工作队列会重用处理线程, 导致threadLocal被重用, 然而transaction注解在service层, 他会在DynamicDataSourceSwitch被设置之前直接去threadlocal拿数据, 本应拿到null, 但是拿到了之前线程的值
 
一般代码调用链:
Repository@Annotation(AOP)-->DefaultSqlSession-->SimpleExecutor-->BaseExecutor.getConnection()-->SpringManagedTransaction.getConnection()--->连接为空-->AbstractRoutingDataSource.getConnection()-->拿到beforeAOP中注入的datasource的key, 所以每次都会动态切换数据源
 
事务代码调用链:
service注解上@transactional-->TransactionInterceptor.interpter()-->TransactionAspectSupport.createTransactionIfNecessary()-->AbstractPlatformTransactionManager.getTransaction()-->DataSourceTransactionManager.doBegin()-->AbstractRoutingDataSource.determineTargetDataSource()[lookupKey==null去拿默认的Datasource]-->但是发现一个新的请求threadlocal中拿的lookup key不为空, 如果key为从库则获取到了从库连接而不是主库
Repository@Annotation-->执行一般调用链, 问题在于SpringManagedTransaction.getConnection()-->openConnection()-->DataSourceUtils.getConnection()-->TransactionSynchronizationManager.getResource(dataSource)不为空, 所以不会再去调用DynamicDataSource去获取数据源
 
问题解决, DataSourceAdvice AfterReturn需要删除threadLocal中的数据源key 
 
bubuko.com,布布扣
public class DataSourceAdvice
implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {

private static final Logger LOG = LoggerFactory.getLogger(DataSourceAdvice.class);

@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target)
throws Throwable {
DataSourceSwitcher.clearDataSource();
}

}
bubuko.com,布布扣

 

Transaction事务注解和DynamicDataSource动态数据源切换问题解决,布布扣,bubuko.com

Transaction事务注解和DynamicDataSource动态数据源切换问题解决

标签:c   style   class   blog   code   java   

原文地址:http://www.cnblogs.com/zhwbqd/p/3757060.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!