假设我们进入一个方法并在主线程中启动事务。在此方法中,有一些异步方法,因此我们在该方法内又创建了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,所以您有任何想法来管理它以及如何应用吗?
谢谢
答案 0 :(得分:4)
来自Professional Java for Web Applications by Nicholas S. Williams
Spring中的事务范围仅限于事务开始的线程。然后,事务管理器将事务链接到在事务生命周期中同一线程中使用的托管资源。使用Java Persistence API时,您使用的资源为EntityManager
。它在功能上等同于Hibernate ORM的Session和JDBC的Connection。通常,在开始事务和执行JPA操作之前,您将从EntityManager
获得EntityManagerFactory
。但是,这不适用于代表您管理事务的Spring Framework模型。解决此问题的方法是org.springframework.orm.jpa.support.SharedEntityManagerBean
。在Spring Framework中配置JPA时,它会创建一个SharedEntityManagerBean
代理的EntityManager
接口。然后将此代理注入到您的JPA存储库中。在此代理实例上调用EntityManager
方法时,在后台发生以下情况:
➤➤如果当前线程已经具有真实的EntityManager
,且该事务具有活动事务,则它将调用委托给该EntityManager
上的方法。
➤➤否则,Spring框架将从EntityManager
获取一个新的EntityManagerFactory
,开始一个事务,并将两者都绑定到当前线程。然后,它将调用委托给该EntityManager
上的方法。当事务被提交或回滚时,Spring从线程取消绑定事务和EntityManager
,然后关闭EntityManager
。将来在同一线程上执行@Transactional
操作(即使在同一请求中)也将重新开始该过程,从工厂获得新的EntityManager
并开始新的事务。这样,不会有两个线程同时使用EntityManager
,并且给定线程只有一个事务,并且在任何给定时间只有一个EntityManager
有效。
如果您 不是 使用Spring MVC,那么您将在Hibernate中使用SessionFactory
获得会话。休眠会话代表事务从头到尾的生命周期。取决于您的应用程序的架构方式,可能少于一秒钟或几分钟。在Web应用程序中,它可能是请求中的多个事务之一,持续整个请求的事务或跨多个请求的事务。 Session
不是线程安全的,并且一次只能在一个线程中使用,它负责管理实体的状态。
答案 1 :(得分:0)
这篇文章https://dzone.com/articles/spring-transaction-management-over-multiple-thread-1似乎很好地涵盖了这个问题,并提到了一个正在做类似事情的项目。