JPA фиксирует изменения, выполненные по развернутому соединению

Что происходит при фиксации транзакции от менеджера сущностей, который не содержит грязных объектов? Может ли быть так, что никакая команда COMMIT не отправляется в БД?

У меня были некоторые тестовые случаи, терпящие неудачу время от времени без разумной причины. После некоторого исследования у меня появилась теория, которую я хотел бы подтвердить здесь.

У меня есть небольшой фреймворк для подготовки данных на БД для каждого теста. Светильники используют такой метод для хранения объектов в БД с использованием JPA (Hibernate):

  public <R> R doInTransaction(final Function<EntityManager, R> whatToDo) {
    final EntityManager em = emf.createEntityManager();
    final R result;
    try {
      try {
        em.getTransaction().begin();
        result = whatToDo.apply(em);
        em.getTransaction().commit();
      } finally {
        if (em.getTransaction().isActive()) {
          em.getTransaction().rollback();
        }
      }
    } finally {
      em.close();
    }
    return result;
  }

Итак, прибор вызывает этот метод, передавая функцию whatToDo, где объекты сохраняются, и метод оборачивает транзакцию вокруг переданной функции. Мои неудачные тестовые случаи используют приспособление, которое опирается на унаследованный код, который использует хранимые процедуры и хранит объекты напрямую через JDBC, т.е. вместо использования em.persist()Я использую следующее в переданной функции для вызова хранимых процедур:

em.unwrap(Session.class).doWork(connection -> {
  // stored procedures are called here directly over JDBC
});

Итак, моя теория заключается в том, что JPA при этом обстоятельстве не фиксирует немедленно, поскольку нет никаких грязных объектов JPA, управляемых EntityManager. Следовательно, фактическая фиксация происходит только позже, то есть после подтверждения моего теста, и тест не пройден. Может ли это быть?

Каково транзакционное поведение Hibernate при "разворачивании" соединения из EntityManager?

Я добавил сейчас em.flush() перед em.getTransaction().commit() и это, кажется, помогает, но я все еще не уверен на 100%, что это решает проблему. Кто-нибудь может подтвердить?

1 ответ

Поведение остается одинаковым независимо от развертывания соединения. если вы не используете JTA, альтернативой является базовая транзакция, предоставляемая JDBC, то есть локальная транзакция. (или вы можете реализовать свой собственный поставщик управляемых транзакций)

Когда вы разворачиваете соединение и работаете непосредственно с JDBC, вы все равно получаете то же соединение, которое изначально получено этим менеджером сеанса / сущности. Так что это тот же эффект.

Другие вопросы по тегам