Spring自带线程池(ThreadPoolTaskExecutor)用在Spring Event,在执行过程中,发生异常事务会回滚吗

背景
  1. 推荐阅读Spring的event的基本使用过程与理解
  2. 测试当线程池中的任务发生异常(RuntimeException)不捕获与@Transactional关系
过程
  • 测试事务(入口处没有注解@Transactional)
  1. 测试逻辑。业务逻辑代码先执行了数据库的更新操作,后续逻辑发生空指针异常。
  2. 数据库情况
    在这里插入图片描述
  3. 代码情况
    监听代码情况
	@EventListener
    @Async("AsyncTaskExecutor")
    public void handleMyEvent(MyEvent myEvent) {
        System.out.println("线程:" + Thread.currentThread().getName() + "执行了MyEvent事件");

        // 具体的业务逻辑过程
        this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
    }

具体业务逻辑代码。
studentService.selectByName()和studentService.update()都添加了@Transactional注解。异常是RuntimeException,因此Spring是能够感知到的。

	@Override
    public void handleEvent(String addr, Date time, String operator) {
        System.out.println("event: 模拟具体的业务逻辑处理过程, 这里单纯地打印出来即可");
        System.out.println("myEvent.addr: " + addr);
        System.out.println("myEvent.time: " + time);
        System.out.println("myEvent.operator: " + operator);
        Student sara = studentService.selectByName("sara");
        sara.setName("Ted");
        studentService.update(sara);
        String str = null;
        System.out.println(str.equals("null"));

    }
  1. 测试结果(未回滚,数据被修改 了)
    在这里插入图片描述
  • 测试事务(入口处有注解@Transactional),其他为原来初始情况。
    监听代码
	@EventListener
    @Async("AsyncTaskExecutor")
    @Transactional
    public void handleMyEvent(MyEvent myEvent) {
        System.out.println("线程:" + Thread.currentThread().getName() + "执行了MyEvent事件");

        // 具体的业务逻辑过程
        this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
    }

测试结果(回滚了,没有修改成功)
在这里插入图片描述

  • 测试事务(入口处没有注解@Transactional,业务逻辑入口处有@Transactional ),其他为原来初始情况。
 	@EventListener
    @Async("AsyncTaskExecutor")
    public void handleMyEvent(MyEvent myEvent) {
        System.out.println("线程:" + Thread.currentThread().getName() + "执行了MyEvent事件");

        // 具体的业务逻辑过程
        this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
    }
 	@Override
    @Transactional
    public void handleEvent(String addr, Date time, String operator) {
        System.out.println("event: 模拟具体的业务逻辑处理过程, 这里单纯地打印出来即可");
        System.out.println("myEvent.addr: " + addr);
        System.out.println("myEvent.time: " + time);
        System.out.println("myEvent.operator: " + operator);
        Student sara = studentService.selectByName("sara");
        System.out.println(sara.getName());
        sara.setName("Ted");
        studentService.update(sara);
        String str = null;
        System.out.println(str.equals("null"));

    }

测试结果(事务回滚)
在这里插入图片描述

  • 测试事务(入口处有注解@Transactional,业务逻辑入口处有@Transactional ,studentService.update(sara)@Transactional去掉)。
 	@EventListener
    @Async("AsyncTaskExecutor")
    public void handleMyEvent(MyEvent myEvent) {
        System.out.println("线程:" + Thread.currentThread().getName() + "执行了MyEvent事件");

        // 具体的业务逻辑过程
        this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
    }
 	@Override
    @Transactional
    public void handleEvent(String addr, Date time, String operator) {
        System.out.println("event: 模拟具体的业务逻辑处理过程, 这里单纯地打印出来即可");
        System.out.println("myEvent.addr: " + addr);
        System.out.println("myEvent.time: " + time);
        System.out.println("myEvent.operator: " + operator);
        Student sara = studentService.selectByName("sara");
        System.out.println(sara.getName());
        sara.setName("Ted");
        // 此方法没有@Transactional
        studentService.update(sara);
        String str = null;
        System.out.println(str.equals("null"));

    }

测试结果(事务回滚)
在这里插入图片描述

小结
  • Spring的线程池用在Event中,如果线程池中的线程在处理业务逻辑的过程中,发生了RuntimeExcepion时,与Spring注解@Transactional用在的哪个层级,然后导致事务会回滚,有非常大的关系。这个demo实验有很好的参考价值
  • 注意@Transactional默认回滚的异常级别是RuntimeExcepion,而不是Excption
  • @Transactional。Spring默认的传播行为REQUIRED,业务方法需要在一个事务中运行,如果方法运行时,已处在一个事务中,那么就加入该事务,否则自己创建一个新的事务。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值