@Transactional注解失效场景及解决方案

@Transactional注解不生效原因及解决方案

今天再工作中遇到了一个问题:再插入数据前需要进行操作记录,因此再service层调用的保存操作记录的方法,考虑到操作记录不应被后面的操作所影响,因此将事务的传播型为设置为REQUIRES_NEW(如果当前有事务存在,将当前事务挂起,重新开启新事务执行。事务的提交或回滚不受之前事务的影响)测试时发现即使设置了REQUIRES_NEW后保存操作记录的方法仍然回被后面的代码所影响,后面代码报错,操作记录的事务也被回滚了,原因是没有通过代理对象去调用方法,因此事务没有被代理对象处理@Transactional事务失效了。

模拟当时的场景:

数据库内有user1表,name的长度为5,serivice中有save和saveLog方法再save方法内调用saveLog方法。

create table user1(
	id int primary key auto_increment,
	name varchar(5),
	create_date datetime
);

service:

@Service
public class User1Service {

    @Autowired
    private User1Mapepr user1Mapepr; //mybaits的mapper
	
    //这里传播行为声明为REQUIRED(如果当前没事务,创建事务,否则加入到当前事务)
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void save(){
		//先保存记录
        saveLog();
        //后保存用户(这里会报错,因为name字段长度超过数据库规定的5字符)
        user1Mapepr.save(new User1(null,"zs1111111111",new Date()));
    }

    //传播行为声明为REQUIRES_NEW(不管当前是否有事务,都创建新事务运行)
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public void saveLog(){
        //这里保存用户,能正常执行
        System.out.println("saveLog");
        user1Mapepr.save(new User1(null,"s1",new Date()));
        System.out.println("=======保存成功=======");
    }
}

执行后发现,虽然事务传播行为为REQIREES_NEW但是并没有创建新事务去执行,原因是没有通过代理对象调用saveLog方法,因此@Transactional事务失效

解决办法:

通过AopContext获取当前对象的代理对象后调用saveLog方法

@Service
public class User1Service {

    @Autowired
    private User1Mapepr user1Mapepr;

    @Autowired
    private Service2 service2;


	//这里传播行为声明为REQUIRED(如果当前没事务,创建事务,否则加入到当前事务)
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void save(){
        //通过AopContext.currentProxy()获取当前对象的代理对象
        User1Service aopService = (User1Service)AopContext.currentProxy();
        //spring还为我们提供了AopUtils工具类
        System.out.println("是否是aop对象===>"+AopUtils.isAopProxy(service));
        System.out.println("是否是CGLIB===>"+AopUtils.isCglibProxy(service));
        System.out.println("是否是JDK===>"+AopUtils.isJdkDynamicProxy(service));
        //调用aop代理对象保存日志
        aopService.saveLog();
		
        user1Mapepr.save(new User1(null,"zs1111111111",new Date()));

    }
	//传播行为声明为REQUIRES_NEW(不管当前是否有事务,都创建新事务运行)
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public void saveLog(){
        //这里保存用户,能正常执行
        System.out.println("saveLog");
        user1Mapepr.save(new User1(null,"s1",new Date()));
        System.out.println("=======保存成功=======");
    }

}

执行后,即使后面保存用户报错,也不影响saveLog事务的执行,@Transactional能后正常执行

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值