最近开发,有地方需要用到多线程,每个线程里面处理多个方法,过程中遇到了一个问题,我们使用平时的@Transactional注解,就是当前一个方法执行完成(比如插入操作),后一个方法是不会事务回滚的。当时觉得很不可思议,后来经过半天时间,终于挖出原因,并成功解决。
我这里先说明原因:多线程底层连接数据库的时候,时使用的线程变量(TheadLocal),所以,开多少线程理论上就会建立多少个连接,每个线程有自己的连接,事务肯定不是同一个了。
解决办法:我强制手动把每个线程的事务状态放到一个同步集合里面。然后如果有单个异常,循环回滚每个线程。
代码如下:

 //先在开启多线程外面,定义一个同步集合:
 List<TransactionStatus> transactionStatuses = Collections.synchronizedList(new ArrayList<TransactionStatus>());
 //开启多线程
 executorService.execute(new Runnable() {
          @Override
          public void run() {
          DefaultTransactionDefinition def = new DefaultTransactionDefinition();
              def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务,这样会比较安全些。
              TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
              transactionStatuses.add(status);
              try{
                  //逻辑1
                  ...
                  //逻辑2
                  ...
              
              }catch(Exception e){
              
              }
          
          }

crawler
327 声望79 粉丝

专注技术多年,曾任职京东,汉得等公司主研