Spring主从数据库切换,事务失效

前言

多数据库切换时候,存在事务,导致数据库切换失败,读写分离无法完成。其原因在于DataSourceTransactionManager类中,事务处理的方式,摘取部分源码,如下:

@Override
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        .......
            // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
            // so we don't want to do it unnecessarily (for example if we've explicitly
            // configured the connection pool to set it already).
            if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if (logger.isDebugEnabled()) {
                    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }
                con.setAutoCommit(false);
            }
            txObject.getConnectionHolder().setTransactionActive(true);
       .......
    }

因为建立数据源链接在一些连接驱动中是非常耗时的处理,所以为了避免这样的操作,在事务处理的时候,会先把数据源放入缓存中,等待事务处理完成才会清除缓存,所以如果在service层中的方法中添加了事务,并且方法中存在切换数据源的操作,将会导致切换失败。情景如下:

@Transactional
public Integer updateType(TypeDto typeDto) {
        ....
        TypeModle oldTypeModle = typeDao.findById(typeDto.getId());
        ....
        return this.enumTypeDao.updateById(oldtypeModle);
    }
解决方法及思路
  • 思路
    在获取事务锁定数据源之前切换数据源。

  • 方法一
    将事务处理放在DAO层,切面放在SERVICE层。

//Service层
@Before("execution(* cn.ymanager.service..*.*(..))")
    public void dbAspect(JoinPoint point){
        .....
    }
//DAO层
@Transactional
public interface Dao extends BaseDao {
    ...........    
}
  • 方法二
    如上所说,因为切换数据源的时候,事务先执行了,导致切换数据库失败。也可以从事务方法入手。在DataSourceTransactionManager类的dobegin方法中修改。
    创建自己的类,继承DataSourceTransactionManage,重写dobegin方法。因为dobegin方法是在类AbstractRoutingDataSource的determineCurrentLookupKey()前执行。
public class SpayTransactionManager extends DataSourceTransactionManager {

    @Override
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        ...
        //写入自己的逻辑判断,并且切换到自己想到数据库
        super.doBegin(transaction, definition);
    }
}

关于主从数据库切换可参考此篇文章
SpringMVC主从数据库切换

你可能感兴趣的:(Spring主从数据库切换,事务失效)