最近有一个需求——当删除旧数据并保存新数据时,只有成功删除旧数据并保存新数据才能回滚,因为新数据保存的数据量相对较大,然后在主线程中删除数据。
在方法上加上以下注释,似乎不可能,因为主线程和子线程不是同一个事务
@Transactional(rollbackFor = Exception.class)
@Transactional故障如下
1.
是基于动态代理来实现的,非public的方法,动态代理对象信息为空,不能回滚。
@Transactional它是基于动态代理对象实现的,类内部方法的调用是通过this关键词没有动态代理对象,所以事务回滚无效。
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.error("保存失败!") : R.ok(); }