【发布时间】:2023-04-03 23:10:02
【问题描述】:
我是第一次在 WebSphere Commerce 7 环境中使用 JPA。我能够使用容器管理的持久性使其一切正常,因此它可以自行保存对象。问题是,我需要确保在事务存在的逻辑结束之前将数据保存到数据库中,因为如果数据未提交到最后可能会引入竞争条件的更多逻辑数据库之前。如果我在我调用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,我希望将它做成可以传递值的东西,并让它根据我传入的字符串为我创建一个特定的持久性单元。正因为如此,我似乎是执行看起来已经是应用程序管理事务所需的逻辑类型的逻辑。为了完成这项工作,我必须调用Persistence.createEntityManagerFactory(persistenceUnitName) 来创建一个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,它们返回一个对象,该对象具有所有持久性注释以映射到我的数据库。我将 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?如果是这样,当我不为我的EntityManagerFactory 或Entitymanager 使用注射时,为什么我能够做到这一点?顺便说一句,我尝试了有和没有先调用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 和/或 EntityManager 对象,但它们最终也都为 null。所以我做错了什么,以至于这些注入尝试至少没有成功。
谁能帮帮我?谢谢,如果你能做到这一点......
【问题讨论】: