有人可以向我解释为什么Web Sphere Application Server 8.5.5在JTA模式下不提交(甚至开始?)事务。
我有一个带有注释的dao类
@Stateless
@TransactionManagement(value = TransactionManagementType.CONTAINER)
我有一个用@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
注释的方法。该方法只是将一些实体插入数据库(如果它们尚不存在)。
for (MyEntity entity : entities) {
if (validate(entity) { // Programmatic bean validation, returns true when ok
getEntityManager().persist(entity);
}
}
使用嵌入式GlassFish中的Arquillian进行测试,这非常有效。我可以在此方法完成后断点停止Eclipse(Luna& Kepler)中的代码并检查db是否有数据。测试中使用的数据与在WAS上部署时使用的数据相同。 (单独测试时,验证错误会正确显示)
根据说明(http://docs.oracle.com/javaee/6/tutorial/doc/bncij.html)
代码不包含开始和结束交易的语句......
我可能无法理解这一点,因为我必须使用以下方法显式包装方法内容:
getEntityManager().getTransaction().begin();
... The persist loop ...
getEntityManager().getTransaction().commit();
......做出坚持不懈的工作。 如果我不这样做,就没有任何东西放到数据库中。
我还注入了额外的资源来检查交易状态
@Resource
private TransactionSynchronizationRegistry tsr;
并将其放在方法的末尾
System.out.println("Transaction status: " + tsr.getTransactionStatus());
getEntityManager().flush();
输出是:
交易状态:0
其中0 = Status.STATUS_ACTIVE
然而,在'同花顺'时,引发了一场惨败:
javax.persistence.TransactionRequiredException:
Exception Description: No transaction is currently active
我花了好几天试图在WAS上解决这个问题,而我一直在使用嵌入式GlassFish(v3)测试。 两者都使用JavaEE6(和java 6),但是对于Eclipse中的调试,我必须切换到JavaEE7 + Java7。
在此之前的另一个项目中,我在GlasFish v4上做了类似的代码而没有任何问题。
所以有人可以澄清一下,如果有一些WAS特定要求来完成这项工作,或者我只是需要与WAS完全相反而不是说明说明以及我如何理解事情应该有效?
我已经在WAS上进行了以下配置: (管理控制台)
服务器>服务器类型> WebSphere应用程序服务器> server1>容器服务>默认Java持久性API设置>默认JTA数据源JNDI名称='jdbc / kr'(与我的persistence.xml中配置的相同)
资源> JDBC> JDBC提供程序> Oracle JDBC驱动程序(ping好) (当创建它时)'Implementation type'被设置为'connection Pool Datasource',但我也尝试使用'XA'。
// UPDATE
getEntityManager方法只返回超类中注入的实体管理器。
public abstract GenericDAO<T extends GenericEntity> {
@PersistenceContext
private EntityManager em;
...
public EntityManager getEntityManager() {
return this.em;
}
}
// GenericEntity is an interface to force the entities to have the "get all" named query.
该类使用泛型dao -pattern(你从这个Single DAO & generic CRUD methods (JPA/Hibernate + Spring)得到了想法,虽然我有自己的修改,因为它是一个带有默认CRUD方法的抽象类)。 当使用metdhod getEntityManager 而不是直接访问资源时,如果真正的dao-class决定使用它自己的,则可以覆盖超类中使用的实体管理器。 =&GT;此外,超类还有getEntityManager调用,如果在实现类时重写它,它将在抽象中获得与实际实现类所使用的相同的em。此外,当您可以获取em并在需要时逐出数据时,此方法也可用于测试。 这样,您可以在访问em时轻松添加日志记录(日志拦截器)。
//更新2
我发现有一个单独的资源管理器用于获取远程资源(ejb)。这样可以从属性文件中配置ejb的位置。然而内注射仍然在我的这项服务的范围内。
我开始认为这可能导致容器损失了它的交易处理能力?
另外我注意到路径中有一个@Singleton
范围的bean使用实际的事务资源。我无法找到关于bean应该是什么范围的明确解释(可能没有任何要求),但我最终理解dao应该是@Stateless
。
在JavaEE7中,这更加清晰,因为有@Transactional
注释用于指向它。