gpt4 book ai didi

java - Spring事务管理器不是线程安全的?

转载 作者:行者123 更新时间:2023-12-02 06:14:29 24 4
gpt4 key购买 nike

我目前在使用 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

正如您所看到的,已收到两个不同的对象并且两个不同的线程正在运行。但交易是一样的。

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

最佳答案

来自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 配置可能会有所帮助,但从您的代码中,我可以看到您正在将 getTransaction().hashCode() 记录为事务 ID,假设它们引用相同的事务对象,而 hashCode() 不需要为不同的对象返回不同的值。可能有 2 个不同的事务正在进行中,并且两者具有相同的哈希码值。

关于java - Spring事务管理器不是线程安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19768918/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com