【问题标题】:Using Spring Transactions with multiple threads [duplicate]使用具有多个线程的 Spring Transactions [重复]
【发布时间】:2014-12-04 08:00:25
【问题描述】:

这个问题我已经被问过很多次了,现在一直困扰着我。

我们有一个包含 3 个 DAO 方法的服务类,用于更新 3 个不同的表。 该设计使得对所有三个表的更新都应该是原子的。 我有 3 个线程分别调用我的服务类,并且对于每个 DAO 方法更新, 如何使用 Spring 事务或任何事务管理器将所有线程(操作)保持在单个事务下? 任何想法或指向文档的指针? 谢谢!!

【问题讨论】:

标签: java multithreading spring spring-mvc transactions


【解决方案1】:

服务方法应该是启动事务的方法

服务方式

public class Service{
// define dao1,dao2,dao3
@Transactional
public someMethod(){
   dao1.someUpdate();
   dao2.someUpdate();
   dao3.someUpdate();
}
}

Dao1.class

 public class Dao1{

      @Transactional (propagation = Propagation.MANDATORY)
      public someUpdate(){

      }
    }

Dao2 和 Dao3 类似

someUpdate() 将使用 Service.class 的 someMethod() 启动的事务

【讨论】:

  • 感谢您的回复。如果我理解您的解决方案是正确的,那么这三个 dao 方法由一个线程运行,该线程在事务中调用 somemethod()。我的问题是使用 3 个线程分别(同时)执行这三种方法。有什么建议吗?
  • 你找到答案了吗?
【解决方案2】:

这可以通过将事务保持在线程级别来实现。但是,您需要所有这些线程之间的共享对象。此共享对象将跟踪所有这些线程的状态,并在其中任何一个失败时通知它们。如果此线程收到失败通知,它们自己可以抛出异常,并且它们的事务将被回滚。

示例代码

单个线程中的代码

    @Transactional(rollbackFor = Exception.class)
    public void saveData(Product product, ProductStatusObject productStatusObject) throws Exception {
        productDao.persist(product);
        if(product.getId() == 5) {
            productStatusObject.updateCounter(false);
        } else {
            productStatusObject.updateCounter(true);
        }
        if(!productStatusObject.getStatus()) {
            throw new Exception();
        }
    }

共享类中的代码

    private final int  totalThreads;

    private int executedThreads = 0;
    private Boolean finalStatus = true;
    
    public ProductStatusObject(int totalThreads) {
        this.totalThreads = totalThreads;
    }
    
    public synchronized void updateCounter(Boolean threadStatus) throws InterruptedException {
        executedThreads ++;
        if(!threadStatus) {
            this.finalStatus = false;
        }
        if(totalThreads == executedThreads) {
            notifyAll();
        } else {
            wait();
        }
        
    }
    
    public synchronized Boolean getStatus() {
        return finalStatus;
    }

这里的失败条件是如果任何线程正在保存 id 为 5 的数据,所有线程都将回滚它们的代码。否则一切都会成功

【讨论】:

    猜你喜欢
    • 2013-03-02
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 2020-06-19
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多