Java-主线程捕获子线程异常并回滚子线程及主线程

        最近有个需求-当删除旧数据然后保存新数据时,只有删除旧数据成功同时保存新数据成功才可以不然的话就回滚,因为新数据保存那数据量比较大由子线程完成,然后删除数据是在主线程完成。

在方法上加上如下注解,看似可以其实不行,因为主线程与子线程不是同一个事务

@Transactional(rollbackFor = Exception.class)

@Transactional失效有如下场景

  1.@Transactional修饰的方法为非public方法

        因为@Transactional是基于动态代理来实现的,非public的方法,@Transactional的动态代理对象信息为空,所以不能回滚。

  2.在类内部没有添加@Transactional的方法,调用@Transactional方法时

@Transactional是基于动态代理对象来实现的,而在类内部的方法的调用是通过this关键字来实现的,没有经过动态代理对象,所以事务回滚失效。

  3.在@Transactional方法内部捕获了异常,没有在catch代码块里面重新抛出异常,事务也不会回滚

  4.方法用final或static修饰

        如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法而添加事务功能。

  5.未被spring管理

        通常情况下,我们通过@Controller、@Service、@Component、@Repository等注解,可以自动实现bean实例化和依赖注入的功能。

  6.未开启事务

  7.多线程调用

        同一个事务,其实是指同一个数据库连接,只有拥有同一个数据库连接才能同时提交和回滚。

  8.表不支持事务

        可以看看数据库引擎        

创建事务管理器

@Component
public class txManagerConfig {
    // 创建事务管理器
    @Bean(name = "txManager")
    public PlatformTransactionManager txManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

实现代码

    @Autowired
    private PlatformTransactionManager txManager;

    private boolean isExec = false;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R save(List<XXXDataDTO> params) {
        if (params == null || params.isEmpty()) {
            return R.error("没有数据,保存失败!");
        }
        try {
            //判断有无该条记录的旧数据,有则删除
            ......
            //开启线程,执行新数据保存
            Callable<Object> callable = new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
                    TransactionStatus status = txManager.getTransaction(def);
                    try {
                        //新数据保存
                     ......
                        // 提交事务
                        txManager.commit(status);
                    } catch (Exception e) {
                        // 回滚事务
                        txManager.rollback(status);
                        throw new RuntimeException();
                    }
                    return "success";
                }
            };
            FutureTask<Object> futureTask = new FutureTask<Object>(callable);
            thread = new Thread(futureTask);
            thread.start();
            System.out.println(futureTask.get());
        } catch (Exception e) {
            e.printStackTrace();
            isExec = true;
            throw new RuntimeException("xxx保存失败!");
        } finally {
            if (thread.isAlive()) {
                thread.interrupt();
            }
        }
        return isExec ? R.error("保存失败!") : R.ok();
    }

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

像向日葵一样~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值