2013-11-04 88 views
3

我目前遇到了Spring事务管理器的意外行为:将同一事务分配给多个线程。 该场景是在Tomcat服务器中运行的CXF webservice。该服务本身是一个Spring bean(单例)。当发送很多并行请求(在我的测试中,我使用10)到服务器时,有时会发生两个请求(运行在不同线程中)使用相同的事务。由于逻辑被设计为每个请求使用一个事务,所以这种行为会导致应用程序的错误行为。春季交易管理器不是线程安全的吗?

下面我服务类:

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是暴露为服务操作的方法。

当多个线程调用我得到以下日志行:

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 

正如你可以看到两个不同的对象已经收到,两个不同的线程在运行。但交易是一样的。

这是怎么发生的?而且 - 更重要的是 - 如何避免?

+0

我正在使用Spring 3.0.6 Hibernate 3.5.6-Final CXF 2.4.3 –

回答

0

HibernateTransactionManager的javadoc:

绑定一个Hibernate的Session从指定的工厂线程,可能允许每个工厂一个线程绑定的会话...此事务管理器是适用于使用一个单一的应用程序Hibernate的SessionFactory事务性数据访问,...

可能会有所帮助来发表您的Hibernate配置,但是从你的代码,我可以看到你正在登录getTransaction().hashCode()作为交易ID假设它们指向同一个交易对象,而0不需要为不同的对象返回不同的值。可以有两个不同的正在进行的交易,它们都具有相同的散列码值。