想实现回滚,首先要保证 Spring Boot 开启了事务(在启动类上增加 @EnableTransactionManagement 注解开启事务(其实 Spring Boot 默认就是开启事务的),其次就是实现回滚的方法必须是 public 的。
@Transactional(rollbackFor=Exception.class) 表示的是该方法无论抛出什么异常都会进行自动回滚;如果不加 (rollbackFor=Exception.class) 的话,则代表了默认值,也就是只有当该方法抛出了运行时异常(RuntimeException)时才会进行回滚。
由于事务的四大特性(原子性、一致性、隔离性、持久性),所以 @Transactional 一般是要加在业务层(也就是接口实现类)中。
如果将 @Transactional(rollbackFor=Exception.class) 加在了接口实现类上,那么这个类下的所有方法都将会被加上事务管理,即所有方法都会在自己出现异常时进行回滚操作。
/**
* 插入会员信息
*
* @param cashierMember 会员信息
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertCashierMember(CashierMember cashierMember)
{
cashierMember.setCreateTime(DateUtils.getNowDate());
cashierMember.setCreateBy(ShiroUtils.getLoginName());
SMSUtil.sendCreateMemberMessage(cashierMember.getPhonenumber());
return cashierMemberMapper.insertCashierMember(cashierMember);
}
很多方法中都会用 try-catch 对异常进行处理,如果此时在 catch 中对可能出现的异常进行了处理,但是并没有再手动抛出(throw)异常,Spring 则会认为该方法成功执行,也就不会进行回滚👇
正解如下👇
/**
* 插入会员信息
*
* @param cashierMember 会员信息
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertCashierMember(CashierMember cashierMember)
{
try {
cashierMember.setCreateTime(DateUtils.getNowDate());
cashierMember.setCreateBy(ShiroUtils.getLoginName());
SMSUtil.sendCreateMemberMessage(cashierMember.getPhonenumber());
return cashierMemberMapper.insertCashierMember(cashierMember);
}catch (Exception e){
System.out.println("方法出现异常:" + e);
//手动抛出异常
throw new RuntimeException();
}
}
P.S. 如果 try-catch 语句在 finally 语句块中进行了 return 操作,那么 catch 语句块中手动抛出的异常也会被覆盖,同样不会自动回滚。
手动回滚
手动回滚的实现方式也非常简单,只需要添加一句代码即可实现👇
/**
* 插入会员信息
*
* @param cashierMember 会员信息
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertCashierMember(CashierMember cashierMember)
{
try {
cashierMember.setCreateTime(DateUtils.getNowDate());
cashierMember.setCreateBy(ShiroUtils.getLoginName());
SMSUtil.sendCreateMemberMessage(cashierMember.getPhonenumber());
return cashierMemberMapper.insertCashierMember(cashierMember);
}catch (Exception e){
System.out.println("方法出现异常:" + e);
//实现手动回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return 0;
}