900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Java-主线程捕获子线程异常并回滚子线程及主线程

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

时间:2022-04-17 05:14:11

相关推荐

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.表不支持事务

可以看看数据库引擎

创建事务管理器

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

实现代码

@Autowiredprivate 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>() {@Overridepublic Object call() throws Exception {DefaultTransactionDefinition def = new DefaultTransactionDefinition();def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);TransactionStatus status = txManager.getTransaction(def);try {//新数据保存......// 提交事务mit(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();}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。