通过多线程调用的Spring @Transactional方法(多请求)

Jer*_*yJi 3 java spring multithreading transactions spring-mvc

Java Web
Spring MVC框架

在服务级别,我编写了一个@Transactional方法。通过这种方法,我更新了数据库中的一些数据,然后稍后从数据库中读取数据。令我惊讶的是,当在同一线程内有多个请求到达时,数据更改是可见的(应该是),而数据更改在其他线程中不可见。
一种方法的不同线程不是作为一个事务构建的吗?
如果仍然要使用事务,并且希望在不同线程中调用的同一方法位于一个事务中,该怎么办(数据的变化可以彼此看到)?

Far*_*raz 6

我从书上抄袭这个专业的Java Web应用程序尼古拉斯·S.·威廉姆斯

对事务和实体管理器使用线程

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

?? 如果当前线程已经具有EntityManager带活动事务的实数,则它将调用委托给该方法上的方法EntityManager

?? 否则,Spring Framework EntityManager将从中获取新的内容 EntityManagerFactory,启动事务,并将两者都绑定到当前线程。然后,将调用委托给上的方法EntityManager。当事务被提交或回滚时,Spring EntityManager从线程取消绑定事务和 ,然后关闭EntityManager@Transactional 在同一线程上进行的后续操作(即使在同一请求中)也将重新开始该过程,EntityManager从工厂获取新的内容并开始新的事务。这样,就不会有两个线程同时使用an EntityManager,并且给定线程只有一个事务,并且EntityManager在给定时间只有一个 活动。

(我对以上内容作了一些解释)

我认为它可以自我解释并回答您的问题。但是我想补充一点,如果您不使用Spring MVC,那么您将SessionFactory在Hibernate中使用该会话。Hibernate Session代表事务从头到尾的生命周期。取决于您的应用程序的架构方式,可能少于一秒钟或几分钟。在Web应用程序中,它可能是请求中的多个事务之一,持续整个请求的事务或跨多个请求的事务。A Session不是线程安全的,并且一次只能在一个线程中使用,它负责管理实体的状态。


fre*_*man 5

您可能想使用注释isolation参数@Transactional。Spring 默认使用.. hm..DEFAULT由数据库设置,所以可能会有所不同。您可以尝试使用:READ_UNCOMMITTED。更多信息:http : //www.byteslounge.com/tutorials/spring-transaction-isolation-tutorial