fix bug:Spring中事务不生效的问题

2021-12-07 16:49:20 浏览数 (1)

事务注解不生效的问题

出现该问题的主要原因主要有两点:

  • Spring的事务没有生效
  • 出现异常时无法正常回滚

Spring事务不生效的情况

  1. @Transactional用在非public方法上
  2. 未通过代理手段调用事务方法

事务注解用在非public方法上 @Transactional private Access createRecords(AccessDto accessDto); 未通过代理调用的情况:Service正常注入Spring中,在调用方法时使用This调用事务方法,Spring不会注入this,所以无法使用事务。自己调用自己时可以使用Controller直接调用Service //AccessServiceImpl.class //this.AccessRecords(AccessDto accessDto);

出现异常时无法回滚的情况

  1. 未正确处理异常,事务生效也不一定能回滚
  2. 多次数据库操作,未配置事务传播

事务生效不能回滚的情况: try/catch包裹标记了@Transactional注解的方法,方法满足一定条件时才会回滚。 一定条件: ①:只有异常传播除了标记的@Transactional注解的方法,事务才会回滚。 ②:默认情况下,出现RunTimeException(非受检异常)或Error的时候,Spring才会回滚事务。 ③:catch的作用就是捕捉方法中的异常,使回滚不传播到外层事务,以免对其他事务产生影响。

代码语言:javascript复制

 public int createUserWrong1(String name) {
 try {
     this.createUserPrivate(new UserEntity(name));
 } catch (Exception ex) {
     log.error("create user failed because {}", ex.getMessage());
 }
 return userRepository.findByName(name).size();
}

RunTimeException是Exception的子类,Exception包裹了所有的异常,导致异常无法传播出去,导致无法回滚。 ①的解决方案 方案一、手动设置回滚:

代码语言:javascript复制

 //catch异常时:
 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

方案二、使用@Transactional注解的属性

代码语言:javascript复制

 //抛出任何异常时均回滚 
@Transactional(rollbackFor = Exception.class)

上文的方案在这种情况下显然是不适用的:

用户注册时在主表中新增数据,同时需要在子表中关联主表数据,现在业务要求,子表执行错误时回滚,子表不影响主表事务,也就是子表不能影响主流程,需要主表和子表不在同一个事务中。

解决方案:

@Transactional(propagation = Propagation.REQUIRES_NEW)

执行到当前方法时创建一个新的事务。

官方文档:

代码语言:javascript复制
/**
 * Create a new transaction, and suspend the current transaction if one exists.
 * Analogous to the EJB transaction attribute of the same name.
 * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
 * on all transaction managers. This in particular applies to
 * {@link org.springframework.transaction.jta.JtaTransactionManager},
 * which requires the {@code javax.transaction.TransactionManager} to be
 * made available to it (which is server-specific in standard Java EE).
 * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManage
 */

0 人点赞