同一个Class中方法调用Spring事务不起作用

2023-04-12
问题描述

开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方。这是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。


举例说明

在AreaService 类中,如果insert和deleteById开启了事务,但是调用的方法insertDelete没有开启事务,那么这两个被调用的方法也开启不了事务。


@Service
public class AreaService {
      
    @Autowired
    private AreaMapper areaMapper;
    //没有加事务
	public void insertDelete(Area area){
      
        this.insert(area);//虽然方法内部出现异常,但是上面的areaMapper.insert(area);还是会执行并插入到数据库
        int abc = 1/0; //出现异常,程序结束
        this.deleteById(area.getId());//不会执行
    }
	@Transactional(propagation =Propagation.REQUIRES_NEW)
    public int insert(Area area) {
      
        area.setDelFlag(0);
        area.setCreateTime(LocalDateTime.now());
        int insert = areaMapper.insert(area);
        int a = 1/0;//虽然此处出现异常,但是上面的areaMapper.insert(area);还是会执行并插入到数据库
        return insert;
    }
	@Transactional(propagation =Propagation.REQUIRES_NEW)
    public int deleteById(Long id) {
      
        Long[] ids = {
      id};
        return areaMapper.updateDelFlagByIds(ids);
    }
}
解决方法
  1. 注入自身(比较快捷)
  2. 拆成两个类(略有点麻烦)
  3. AopContext.currentProxy()获取代理类(使用起来有点麻烦)
  4. 使用手写事务(容易出现事务未关闭的情况)

注入自身的示例:


@Service
public class AreaService {
      
    @Autowired
    private AreaMapper areaMapper;
    @Autowired
    private AreaService service;//将自身service注入
    //没有加事务
	public void insertDelete(Area area){
      
        service.insert(area);
        int abc = 1/0; //出现异常,程序结束
        service.deleteById(area.getId());//不会执行
    }
	@Transactional(propagation =Propagation.REQUIRES_NEW)
    public int insert(Area area) {
      
        area.setDelFlag(0);
        area.setCreateTime(LocalDateTime.now());
        int insert = areaMapper.insert(area);
        int a = 1/0;//出现异常,事务回滚
        return insert;
    }
	@Transactional(propagation =Propagation.REQUIRES_NEW)
    public int deleteById(Long id) {
      
        Long[] ids = {
      id};
        return areaMapper.updateDelFlagByIds(ids);
    }
}

本文仅代表作者观点,版权归原创者所有,如需转载请在文中注明来源及作者名字。

免责声明:本文系转载编辑文章,仅作分享之用。如分享内容、图片侵犯到您的版权或非授权发布,请及时与我们联系进行审核处理或删除,您可以发送材料至邮箱:service@tojoy.com