简体   繁体   English

Spring Transaction Manager不是线程安全的?

[英]Spring Transaction Manager not threadsafe?

I'm currently experiencing an unexpected behaviour with the Spring transaction manager: the same transaction is assigned to multiple threads. 我目前遇到Spring事务管理器的意外行为:同一事务被分配给多个线程。 The scenario is a CXF webservice running in a Tomcat server. 该场景是在Tomcat服务器中运行的CXF Web服务。 The service itself is a Spring bean (singleton). 服务本身是一个Spring bean(单例)。 When sending many parallel requests (in my test I used 10) to the server it sometimes happens that two requests (running in different threads) work with the same transaction. 当向服务器发送许多并行请求(在我的测试中使用10)时,有时会发生两个请求(在不同线程中运行)与同一事务一起工作。 Since the logic is designed to use one transaction per request this behaviour causes a faulty behaviour of the application. 由于逻辑被设计为每个请求使用一个事务,因此该行为会导致应用程序的错误行为。

Below my service class: 在我的服务类下面:

package ...clientsupport_v1;

import...

@WebService(targetNamespace = ...)
@Transactional(rollbackFor = MyException.class)
public class ClientSupportFacade extends AbstractServiceFacade implements ClientSupportService {

private static final Logger LOG = LoggerFactory.getLogger(ClientSupportFacade.class);

@Autowired
private HibernateTransactionManager transactionManager;

@Autowired
private ClientOrderImporter clientOrderImporter;

@Override
public Advice receiveClientPreAdvice(User user, PreAdvice preAdvice) throws MyException {
    LOG.debug("PreAdvice: " + preAdvice + ", Transaction: " + getTransactionId() + ", Thread: "
            + Thread.currentThread().getName());
...
    return advice;
}

private int getTransactionId() {
    return transactionManager.getSessionFactory().getCurrentSession().getTransaction().hashCode();
}

}

receiveClientPreAdvice is the method exposed as service operation. receiveClientPreAdvice是作为服务操作公开的方法。

When calling with multiple threads I get the following log lines: 当使用多个线程调用时,我得到以下日志行:

2013-10-29 13:59:25.135 DEBUG e.h.p.s.c.c.ClientSupportFacade.receiveClientPreAdvice:42 - PreAdvice: PreAdvice [barcode=90000000002161, ...], Transaction: 420660542, Thread: http-bio-8080-exec-9
2013-10-29 13:59:25.135 DEBUG e.h.p.s.c.c.ClientSupportFacade.receiveClientPreAdvice:42 - PreAdvice: PreAdvice [barcode=90000000002163, ...], Transaction: 420660542, Thread: http-bio-8080-exec-8

As you can see two different objects have been received and two different threads are running. 如您所见,已收到两个不同的对象,并且正在运行两个不同的线程。 Yet the transaction is the same. 然而交易是一样的。

How can this happen? 怎么会发生这种情况? And - even more important - how can it be avoided? 而且 - 更重要的是 - 如何避免它?

From HibernateTransactionManager javadoc: 来自HibernateTransactionManager javadoc:

Binds a Hibernate Session from the specified factory to the thread, potentially allowing for one thread-bound Session per factory ... This transaction manager is appropriate for applications that use a single Hibernate SessionFactory for transactional data access, ... 将Hibernate会话从指定的工厂绑定到线程,可能允许每个工厂一个线程绑定的Session ...此事务管理器适用于使用单个Hibernate SessionFactory进行事务数据访问的应用程序,...

It may be helpful to post your hibernate configuration but from your code, I can see you are logging getTransaction().hashCode() as Transaction ID assuming they refer to the same transaction object while hashCode() is not required to return different values for different objects. 发布你的hibernate配置可能会有所帮助,但是从你的代码中,我可以看到你正在记录getTransaction().hashCode()作为Transaction ID,假设它们引用相同的事务对象,而hashCode()不需要返回不同的值不同的对象。 There can be 2 distinct transactions in progress that both have the same hash-code value. 正在进行的两个不同的事务都具有相同的哈希码值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM