代码编织梦想

项目场景:

搭配使用 - @DS注解,@Transactional注解

微服务项目中,使用Mybatis plus的@DS注解进行数据源切换,@Transactional事务不起作用

1.Mapper

@DS(DsName.EHP)
public interface CustomerMapper extends BaseMapper<Customer> {

    Page<CmsCustomerListBO> getPage(@Param("page") IPage<PromoterMangerRequestBO> page, @Param("ew") Wrapper<PromoterMangerRequestBO> entityWrapper);

}

2.业务类

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setStatus(Long id, Integer status) throws BusinessException {
        if(id == null || status == null){
            throw new BusinessException(BaseExceptionCodes.PARAM_ERROR);
        }
        Customer customer = baseMapper.selectById(id);
        if (customer == null) {
            throw new BusinessException(BaseExceptionCodes.DATA_ERR);
        }
        customer.setStatus(status);
        customer.setChangedBy(SecurityUtils.getCurrentUsername());
        customer.setChangedAt(new Date());
        customerMapper.updateById(customer);

3.报错信息提示

### Error querying database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'adb.customer' doesn't exist
### The error may exist in com/naiterui/ehp/bs/agent/modules/customer/mapper/CustomerMapper.java (best guess)
### The error may involve defaultParameterMap
### The error occurred while setting parameters

原因分析:

主要分析开发常见的三种情况

1.不使用@Transactional,数据源切换正常,但是事务无效
2.使用@Transactional,数据源没有切换
3.使用@Transactional(propagation = Propagation.REQUIRES_NEW),数据源切换,且事务有效


解决方案:

@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
@DS(DsName.EHP)

1.开启事务的同时,会从数据库连接池获取数据库连接;
2.如果内层的service使用@DS切换数据源,只是又做了一层拦截,但是并没有改变整个事务的连接
3.在这个事务内的所有数据库操作,都是在事务连接建立之后,所以会产生数据源没有切换的问题
4.为了使@DS起作用,必须替换数据库连接,也就是改变事务的传播机制,产生新的事务,获取新的数据库连接
5.所以方法上除了加@Transactional外,还需要设置propagation = Propagation.REQUIRES_NEW

注意:需要说明的是,属性Propagation结合@transaction注解使用。

事务传播机制—七种枚举可分三类:

1.支持当前事务的事务传播机制

  1.REQUIRED----无事务新建事务,有则加入这个事务
  2.SUPPORTS----支持当前事务,无事务就以非事务方式执行;注意,如有外部存在事务,加入事务,无则省略
  3.MANDATORY----支持当前事务,当前不存在事务,则抛出异常  	

2.不支持当前事务的事务传播机制

  1.REQUIRES_NEW----存在事务则挂起,重新创建新事物执行,直至事务提交或回滚,原来的事务才会恢复执行
  2.NOT_SUPPORTED---以非事务方式执行,如操作在一个事务中,事务挂起,操作完成后才会恢复事务的执行
  3.NEVER----以非事务方式执行,存在事务则抛出异常

3.嵌套事务机制

  1.NESTED----表示当前有一个事务正在运行,则这方法应该运行在嵌套事务中,被嵌套的事务可独立于提交或回滚。没有事务,则按照REQUIRED机制实行。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_50160384/article/details/130841690