在使应用程序管理的事务在JPA和WebSphere上运行时遇到问题

时间:2019-01-17 21:27:19

标签: java jpa jta

我是在WebSphere Commerce 7环境中第一次使用JPA。使用容器管理的持久性,我可以使它们一切正常,因此它可以按自己的意愿保存对象。问题是,我需要确保在事务存在的逻辑结束之前将数据保存到DB,因为如果没有将数据提交到事务的末尾,还有更多逻辑可能会引入竞争条件。数据库之前。如果我在调用entityManager.persist的点添加调试点,也在调用entityManager.close的点之后添加调试点,则可以查询数据库,但那里没有数据。但是然后,只要我让逻辑运行并到达课程末尾,数据就会显示出来。

所以我想也许我需要尝试应用程序管理的持久性。当我读到如何做的时候,我感到非常困惑,因为看起来我已经在无意间构造了逻辑,但是仍然不允许我管理交易。而且,我尝试的所有操作都会导致某些异常,尤其是当我尝试调用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,希望将其传递给某个值,并使其能够基于传入的String为我创建一个特定的持久性单元。正是由于这个原因,我似乎执行似乎已经是应用程序管理的事务所需的逻辑类型的逻辑。为了使该工作有效,我必须调用Persistence.createEntityManagerFactory(persistenceUnitName)来创建An EntityManagerFactory,因为我将persistenceUnitName传递给了该类。我读到的内容告诉我,这意味着我将要进行应用程序托管-但是,也许对此我错了。无论如何,该类的核心是这样:

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;
  }
}

每当我将此对象传递给其他类时,使用getter都可以访问Entitymanager -也许这是我的错误,试图创建此帮助器类而不是仅在更接近我要持久化数据的位置创建持久性逻辑?

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

所以现在我基本上有了一个DAO,其中包含要保存的填充对象以及一个EntityManager。因此,我在DAO上调用了persist方法,这样可以节省很多时间。

这是所有在调用类中运行时的样子:

// 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始终为空。我什至尝试从InitialContext调用.lookup()创建它,但据我所知,那里没有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和/或EntityManager对象,但是它们最终都以null结束。因此,我做错了什么,以至于这些注入尝试至少没有成功。

有人可以帮助我吗?谢谢,如果你走了这么远……

1 个答案:

答案 0 :(得分:0)

我找到了一种解决方案,使我可以使用以下方式专门在WebSphere环境中访问事务:

TransactionManager.commit();

似乎该方法能够以我未尝试的方式访问UserTransaction上下文。因此,我敢肯定,如果需要的话,我现在也可以这样做,但是,如果这个课程为我做了,为什么不直接使用它呢?