Я впервые использую JPA в среде WebSphere Commerce 7. Я смог заставить все это работать нормально, используя управляемое контейнером постоянство, и поэтому он сохраняет объекты по собственному желанию. Проблема заключается в том, что мне нужно убедиться, что данные сохраняются в БД до конца логики, в которой существует транзакция, потому что в конце имеется больше логики, которая может ввести условие гонки, если данные не переданы в База данных перед рукой. Если я добавлю точки отладки в точку, которую я вызываю 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)
, чтобы создать 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;
}
}
Получатель дает мне доступ к Entitymanager всякий раз, когда я передаю этот объект другим классам - возможно, это моя ошибка, когда я пытаюсь создать этот вспомогательный класс, а не просто создать логику постоянства ближе к тому месту, где я храню данные?
Затем я приступаю к созданию группы DAO, которые возвращают объект, который имеет все аннотации постоянства для сопоставления с моей базой данных. Я передаю экземпляр JpaConnectionHelper каждому DAO, так что теперь у них всех есть доступ к EntityManager и объектам, которые нужно сохранить. Я также даю всем DAO метод .persistDao()
, который будет использовать EntityManager для вызова .persist()
для созданных объектов.
Так что теперь у меня есть DAO с заполненным объектом, который я хочу сохранить, и EntityManager. Поэтому я вызываю постоянный метод в DAO, и он отлично сохраняет.
Вот как все это выглядит в действии от вызывающего класса:
// 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);
Итак, я хочу попробовать это сделать с помощью управляемых приложением транзакций. Я начинаю с того, что просто пытаюсь вызвать entityManager.flush()
после вызова метода persist, но это ничего не делает (также не исключение). Затем я пытаюсь добавить entityManager.getTransaction.commit()
в том же месте, и это выдает исключение, как вы могли ожидать:
You cannot access the EntityTransaction when using managed transactions.
Теперь поправьте меня, если я ошибаюсь, но разве это не означает, что я использую CMT? И если да, то почему я могу, если я не использую инъекции для EntityManagerFactory
или Entitymanager
? Кстати, я пробовал версии этого с и без первого звонка joinTransaction()
Итак, я перечитал больше и обнаружил, что мне может понадобиться ввести транзакцию UserTransaction, поэтому я пытаюсь добавить ее в JPAConnectionHelper (где находится экземпляр EntityManager)
@Resource
private 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");
Это привело к исключениям NamingException для каждого (не смейтесь, этот материал для вас тоже был новым ...)
Так что я даже не могу получить UserTransaction с beginTransaction()
или commit()
.
В качестве теста я также пытался использовать инъекцию, чтобы получить объекты EntityManagerFactory и / или EntityManager, но все они также оказались нулевыми. Так что я делаю что-то настолько неправильное, что эти попытки инъекции ни к чему не привели.
Кто-нибудь может мне помочь? Спасибо, если вы сделали это так далеко ...