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

时间:2016-12-30 05:40:50

标签: java spring multithreading spring-mvc transactions

Java web
Spring MVC框架

在我的服务级别,我写了一个@Transactional方法。在该方法中,我更新数据库中的一些数据,然后稍后从数据库中读取数据。 令我惊讶的是,当多个请求来到同一个线程内时,数据更改是可见的(应该是这样),但是数据更改在其他线程中不可见。
一个方法构建的不同线程不是一个事务吗? 如果我仍然想要使用事务并且我想在不同的线程中调用相同的方法在一个事务中(可以相互看到数据的变化),我该怎么办?

2 个答案:

答案 0 :(得分:4)

我正在从书Professional Java for Web Applications by Nicholas S. Williams

中复制此内容
  

为交易和实体经理使用线程

     

事务范围仅限于事务开始的线程   然后,事务管理器将事务链接到同一线程中使用的受管资源   在交易期间。使用Java Persistence API时,您使用的资源   是EntityManager。它是Hibernate ORM的Session和JDBC的功能等价物   Connection。通常情况下,您会从EntityManagerFactory获得EntityManager   在开始交易和执行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并开始新的交易。这样,没有两个线程同时使用EntityManager,并且给定线程只有一个事务和一个事务   EntityManager在任何特定时间都有效。

(我将上面的内容翻了一遍)

我认为它是自我解释并回答你的问题。但我想补充一点,如果您不使用Spring MVC,那么您将在Hibernate中使用SessionFactory获得会话。 Hibernate Session代表从开始到结束的事务的生命。根据应用程序的架构方式,可能不到一秒钟或几分钟;在Web应用程序中,它可以是请求中的多个事务之一,持续整个请求的事务或跨越多个请求的事务。 Session,它不是线程安全的,一次只能在一个线程中使用 ,负责管理实体的状态。

答案 1 :(得分:2)

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