Подтвердить что ты не робот

JPA/EclipseLink: Создает ли EntityManager.getTransaction() новую транзакцию или возвращает активную?

Я использую EclipseLink 2.3.0. У меня есть метод, который я вызываю из unit test (следовательно, вне контейнера, без JTA), который выглядит следующим образом:

EntityManager em = /* get an entity manager */;
em.getTransaction().begin();
// make some changes
em.getTransaction().commit();

Изменения не сохранялись в базе данных и долгое время смотрели на это и, наконец, поняли, что EntityManager.getTransaction() фактически возвращает NEW EntityTransaction, а не одно и то же в обоих вызовах. Эффект заключается в том, что первый вызов создает новую транзакцию и начинает ее, а второй вызов создает ДРУГОЕ транзакцию и фиксирует ее. Поскольку первая транзакция никогда не выполнялась, изменения не сохраняются. Мы проверили это следующим образом:

log.info(em.getTransaction().toString());
log.info(em.getTransaction().toString());

Это привело к появлению этих сообщений журнала:

INFO: org.ecl[email protected]1e34f445
INFO: org.eclipse.persistence.internal.jpa.transaction.EntityTrans[email protected]

Два разных идентификатора объекта, которые проверяют наличие двух разных экземпляров. Изменение кода:

EntityManager em = /* get an entity manager */;
EntityTransaction tx = em.getTransaction();
tx.begin();
// make some changes
tx.commit();

... устранил проблему. Теперь, когда я запускаю код, я вижу инструкции SQL, сгенерированные для работы с базой данных, и просматривая в базе данных данные были изменены.

Я был немного удивлен этим результатом, так как я видел множество примеров кода онлайн (для JPA вообще и для EclipseLink специально), которые рекомендуют код, который мы использовали для управления транзакциями. Я искал по всему миру информацию об этом, но ничего не нашел. Итак, что происходит?

Я просмотрел спецификацию JPA для чего-то, что точно определяет, что делает getTransaction(), и не было конкретного, если транзакция является новой или той же. Есть ли параметр в persistence.xml, который контролирует это? Является ли поведение специфичным для каждой реализации спецификации JPA?

Большое спасибо за любую информацию или руководство.

4b9b3361

Ответ 1

Использование getTransaction() работает в JPA и EclipseLink (так работают наши собственные тесты).

Я предполагаю, что вы делаете что-то еще очень странное.

Используете ли вы Spring или другой слой? Пожалуйста, укажите весь код и persistence.xml для вашего теста. Убедитесь, что вы не используете JTA в вашем файле persistence.xml.

Ответ 2

Спецификация JPA (см. параграф 7.5.4) содержит явные примеры, показывающие использование getTransaction() для начала и фиксации транзакции. Таким образом, ваш код должен быть в порядке.

Ваш тест показывает, что вы получаете два разных объекта, но это не означает, что одна и та же транзакция не используется. Возможно, возвращенный объект - это просто некоторый прокси-сервер для одного, реального объекта транзакции.

Или, возможно, транзакция совершена или откат внутри кода, скрытого под // make some changes.

Ответ 3

У вас пытались использовать persist before commit:?

  Employee employee = new Employee("Samuel", "Joseph", "Wurzelbacher");
  em.getTransaction().begin();
  em.persist(employee);
  em.getTransaction().commit();