【问题标题】:Multi-threading Spring Transaction多线程 Spring 事务
【发布时间】:2019-02-10 04:07:12
【问题描述】:

假设我们进入一个方法并在主线程中启动一个事务。在这个方法中,有一些异步方法,所以我们在这个方法中又创建了 2 个线程;

                 Thread 1 --> SubMethod1 --> Saving (t=1)
                   ^
                   |
MainThread --> MainMethod --> Saving (t=3)
                   |
                   v   
                 Thread 2 --> SubMethod2 --> Exception while saving (t=2).

由于线程 2 出现异常,我想回滚其他线程完成的所有事务。但是,尽管可以回滚主线程线程 2 拥有的事务,但我无法回滚线程 1 工作。 我正在使用 Spring/Hibernate,所以您有什么想法来管理它以及如何应用吗?

谢谢

【问题讨论】:

  • 不要使用线程。事务是线程绑定的,您有多个事务。您不能回滚已提交的事务。唯一的“解决方案”是手动撤消工作(删除记录、恢复旧状态等)。

标签: java spring multithreading hibernate spring-transactions


【解决方案1】:

来自Professional Java for Web Applications by Nicholas S. Williams

Spring 中的事务范围仅限于事务开始的线程。事务管理器然后将事务链接到事务生命周期内同一线程中使用的托管资源。使用 Java Persistence API 时,您使用的资源是 EntityManager。它是 Hibernate ORM 的 Session 和 JDBC 的 Connection 的功能等价物。通常,您会在开始事务和执行 JPA 操作之前从EntityManagerFactory 获得EntityManager。但是,这不适用于代表您管理事务的 Spring Framework 模型。这个问题的解决方案是org.springframework.orm.jpa.support.SharedEntityManagerBean。在 Spring Framework 中配置 JPA 时,它会创建一个代理 EntityManager 接口的 SharedEntityManagerBean。然后将此代理注入到您的 JPA 存储库中。当在此代理实例上调用 EntityManager 方法时,后台会发生以下情况:

➤➤ 如果当前线程已经有一个真正的EntityManager 和一个活动事务,它会将调用委托给该EntityManager 上的方法。

➤➤ 否则,Spring Framework 从EntityManagerFactory 获取新的EntityManager,启动事务,并将两者绑定到当前线程。然后它将调用委托给EntityManager 上的方法。当事务被提交或回滚时,Spring 将事务和EntityManager 从线程中解除绑定,然后关闭EntityManager。同一线程上的未来@Transactional 操作(即使在同一请求中)再次启动该过程,从工厂获得新的EntityManager 并开始新的事务。这样,没有两个线程同时使用EntityManager,并且给定线程在任何给定时间只有一个事务和一个EntityManager处于活动状态。

如果您不使用 Spring MVC,那么您将在 Hibernate 中使用 SessionFactory 获得会话。 Hibernate Sessions 代表事务从开始到结束的生命周期。根据您的应用程序的架构方式,这可能不到一秒或几分钟;在 Web 应用程序中,它可以是请求中的多个事务之一、持续整个请求的事务或跨越多个请求的事务。 Session 不是线程安全的,一次只能在一个线程中使用,它负责管理实体的状态。

【讨论】:

  • 假设一个端点需要DELETE FROM 3 个表,然后INSERT INTO 这三个表。插入需要来自其他 2 个不相关表的 SELECT。没有办法通过同时发出所有DELETEs(每个表请求在单独的线程中执行)以及SELECTs(再次:每个数据库请求一个线程)来多线程这个端点,然后是阻塞调用等待所有结果最终在他们自己的线程中发出INSERTs? (所有这些总共有 5 个线程处理所有 8 个请求,而不是一个线程按顺序执行整个工作。)
  • @payne 我目前无法回答这个问题。
【解决方案2】:

这篇帖子https://dzone.com/articles/spring-transaction-management-over-multiple-thread-1 似乎很好地涵盖了这个问题,并提到了一个正在做类似事情的项目。

【讨论】:

    猜你喜欢
    • 2013-05-26
    • 2020-09-11
    • 2021-02-20
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多