让应用程序管理的事务在 JPA 和 WebSphere 上工作时遇到问题

Having problems getting application managed transactions to work on JPA and WebSphere

我是第一次在 WebSphere Commerce 7 环境中使用 JPA。我能够使用容器管理的持久性使其一切正常工作,因此它可以自行保存对象。问题是,我需要确保在事务存在的逻辑结束之前将数据保存到数据库中,因为如果数据未提交到手前的数据库。如果我在我调用 entityManager.persist 的点添加调试点,并且在我调用 entityManager.close 的点之后添加调试点,我可以查询数据库,但那里还没有数据。但是当我让逻辑 运行 顺其自然并到达 class.

的末尾时,数据就会显示出来

所以我想也许我需要尝试应用程序管理的持久性。当我阅读有关如何执行此操作的信息时,我感到非常困惑,因为看起来我已经无意中以这种方式构建了我的逻辑,但它仍然不允许我管理事务。而且我尝试的所有事情都会导致一些异常,尤其是当我尝试调用 getTransaction.commit() 或任何类似的东西来手动提交时。所以这就是我使用 CMT(或者至少我认为是 CMT)所做的工作

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="NIJAVA" transaction-type="JTA">
        <jta-data-source>jdbc/com/ni/jndi</jta-data-source>
        <class>com.ni.commerce.nios.order.objects.NiPnAttributes</class>
        <class>com.ni.commerce.nios.order.objects.NiosAddresses</class>
        <class>com.ni.commerce.nios.order.objects.NiosContacts</class>
        <class>com.ni.commerce.nios.order.objects.NiosHeaders</class>
        <class>com.ni.commerce.nios.order.objects.NiosLines</class>
        <class>com.ni.commerce.nios.order.objects.NiosPayment</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
    </persistence-unit>
    </persistence>

然后我创建了一个 JpaConnectionHelper,我希望把它变成我可以传递一个值的东西,并让它根据我传入的字符串为我创建一个特定的持久性单元。正因为如此,我看起来执行的逻辑似乎已经是应用程序管理事务所需的逻辑类型。为了完成这项工作,我必须调用 Persistence.createEntityManagerFactory(persistenceUnitName) 来创建一个 EntityManagerFactory,因为我将 persistenceUnitName 传递给 class。我读到的东西告诉我这意味着我将进行应用程序管理——但也许我在这方面是错的。总之,那个class的核心是:

public class JpaConnectionHelper {
private EntityManagerFactory emFactory;
private EntityManager entityManager;

private void createEntityManager(String persistenceUnitName) throws ECException {
    setEmFactory(Persistence.createEntityManagerFactory(persistenceUnitName));
    setEntityManager(getEmFactory().createEntityManager());
  }

public EntityManager getEntityManager() {
    return entityManager;
  }
}

每当我将此对象传递给其他 classes 时,getter 使我可以访问 Entitymanager - 也许这是我的错误,试图创建此助手 class 而不是只是创建更接近我持久数据的持久性逻辑?

然后我继续创建一堆 DAO,return 一个具有所有持久性注释的对象映射到我的数据库。我将 JpaConnectionHelper 的实例传递给每个 DAO,所以现在它们都可以访问 EntityManager 和要保存的对象。我还为所有 DAO 提供了一个 .persistDao() 方法,该方法将使用 EntityManager 为创建的对象调用 .persist()

所以现在我基本上有一个 DAO,其中包含我要保存的填充对象,以及一个 EntityManager。所以我在DAO上调用了persist方法,保存的很好。

以下是调用 class:

后所有操作的效果
// creates the EntityManager instance
JPAConnectionHelper jpaConnectionHelper = new JPAConnectionHelper();
// creates the object I want to save to the DB
NiosHeadersDao niosHeadersDao = zwebDaoFactory.getNiosHeadersDao(jpaConnectionHelper);
// this method is simply calling EntityManager.persist(niosHeaders);
niosHeadersDao.persistNiosHeaders();
// close EntityManager (if I try to close the factory it throws exception btw)
zwebDaoFactory.endConnectionScope(jpaConnectionHelper);

所以我想尝试让它与应用程序管理的事务一起工作。我首先尝试在调用 persist 方法后调用 entityManager.flush(),但这什么也不做(也不例外)。然后我尝试在同一个地方添加 entityManager.getTransaction.commit(),这会像您预期的那样抛出异常:

You cannot access the EntityTransaction when using managed transactions.

如果我错了请纠正我,但这不是表明我正在使用 CMT 吗?如果是这样,当我不为我的 EntityManagerFactoryEntitymanager 使用注入时,为什么我可以?顺便说一句,我尝试了有和没有先调用 joinTransaction()

的版本

所以我阅读了更多内容,发现我可能需要注入一个 UserTransaction,所以我尝试将其添加到 JPAConnectionHelper(EntityManager 实例所在的位置)

@Resource
private UserTransaction userTransaction;

但这只会导致始终为空的 userTransaction。我什至尝试通过调用 .lookup() 的 InitialContext 创建它,但据我所知,那里没有 UserTransaction。我尝试了这些尝试:

InitialContext ctx = new InitialContext();
UserTransaction tx = (UserTransaction) ctx.lookup("javax.transaction.UserTransaction");
UserTransaction tx = (UserTransaction) ctx.lookup("java:comp/UserTransaction");

这导致每个 NamingExceptions(别笑,这东西对你来说也是新的......)

所以我什至无法获得 beginTransaction()commit() 的 UserTransaction。

作为测试,我还尝试使用注入来获取我的 EntityManagerFactory and/or EntityManager 对象,但它们最终也都为空。所以我做错了一些事情,以至于这些注入尝试至少没有成功。

谁能帮帮我?如果你能做到这一点,谢谢...

我找到了一个解决方案,可以让我在 WebSphere 环境中使用以下方法访问事务:

TransactionManager.commit();

似乎此方法能够以我未尝试过的方式访问 UserTransaction 上下文。所以我确信如果需要的话我现在也可以这样做,但是嘿,如果这个 class 对我有用,为什么不直接使用那个