java - 多线程 Spring 事务

标签 java spring multithreading hibernate spring-transactions

假设我们进入一个方法并在主线程中启动一个事务。在这个方法中,有一些异步方法,所以我们在这个方法中创建了 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,所以你有什么想法来管理它以及如何应用吗?

谢谢

最佳答案

来自 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 时,它会创建一个 SharedEntityManagerBean 来代理 EntityManager 接口(interface)。然后将此代理注入(inject)到您的 JPA 存储库中。在此代理实例上调用 EntityManager 方法时,后台会发生以下情况:

➤➤ 如果当前线程已经有一个带有 Activity 事务的真实 EntityManager,它会将调用委托(delegate)给该 EntityManager 上的方法。

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

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

关于java - 多线程 Spring 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52177887/

相关文章:

java - 为什么我的嵌套 for 循环不显示 Hello World 2

java - 如何从 SFTP 服务器获取文件列表?

spring - 无法在测试类中导入 applicationContext

java - 如何在 Spring 中从 @RequestMapping 中排除 url 映射?

c++ - 细粒度锁定

java - 在内存中解压缩 *.docx 文件而不写入磁盘 - Java

java - 在旋转排序数组中查找具有重复元素的元素

json - 如何告诉 RestTemplate 使用 UTF-8 编码进行 POST?

c# - System.Threading.ThreadPool 与信号量?

c# - 如何在多线程应用程序中执行文件日志记录