我目前遇到Spring事务管理器的意外行为:同一事务被分配给多个线程。 该场景是在Tomcat服务器中运行的CXF Web服务。服务本身是一个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 :(得分:0)
来自HibernateTransactionManager javadoc:
将Hibernate会话从指定的工厂绑定到线程,可能允许每个工厂使用一个线程绑定的Session ...此事务管理器适用于使用单个Hibernate SessionFactory进行事务数据访问的应用程序,... < / p>
发布你的hibernate配置可能会有所帮助,但是从你的代码中,我可以看到你正在记录getTransaction().hashCode()
作为事务ID,假设它们引用同一个事务对象,而hashCode()
不需要返回不同对象的不同值。正在进行的两个不同的事务都具有相同的哈希码值。