JPA / @PostPersist @PostUpdate - транзакция - PullRequest
17 голосов
/ 04 февраля 2011

В настоящее время я работаю с @PostPersist и @PostUpdate, и в этих триггерах я сохраняю дополнительные сущности.Вопрос в том, являются ли эти триггеры одной и той же транзакцией, и если нет, то можно ли ее форсировать?

Для меня это работает так.Пока я просматривал журналы, транзакция не существует (она фиксируется непосредственно перед запуском триггера), что не позволяет мне (без REQUIRES_NEW в постоянном методе из внедренного компонента) сохранять дополнительные объекты в базе данных.Атрибут REQUIRED полностью игнорируется, а атрибут MANDATORY не вызывает исключение.

Может ли это быть проблемой с JUnit (так как я нахожусь в фазе разработки и не тестировал поведение в полной среде env.)?

Если расширение транзакции по этим триггерам невозможно, как гарантировать, что если откат произойдет до @PostPersist и @PostUpdate, эти операции также будут отменены.

Ответы [ 3 ]

17 голосов
/ 15 ноября 2013

Если вы используете Spring, вы всегда можете зарегистрировать TransactionSynchronization в вашем текущем менеджере транзакций для повторного вызова по таким событиям, как принятие вашей текущей транзакции:

@PostPersist
void onPersist() {
    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {

      @Override
      public void beforeCommit(boolean readOnly) {
        // do work
      }
    });
  }    
}

A TransactionSynchronizationтакже обеспечивает обратные вызовы после успешного завершения транзакции и до / после завершения транзакции.

Если вам необходимо проверить, была ли транзакция зафиксирована или откатана, используйте afterCompletion(int status).

Подробнее см. В JavaDoc TransactionSynchronization .

11 голосов
/ 04 февраля 2011

Запуск события PostPersist не означает, что объект выполнил успешную фиксацию. Откат транзакции может быть выполнен после срабатывания события, но до успешной фиксации. Если вы в PostPersist получите менеджер сущностей, используемый в транзакции, а затем выполните что-то вроде этого:

@PostPersist
void someMethod() {
  EntityManager em = null;
  em = getEntityManagerUsedInTransaction();
  EntityTransaction et = em.getTransaction(); // should return the current transaction
  if (et.isActive() ) {
    // do more db stuff
  }
}

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

0 голосов
/ 24 октября 2015

JPA Внутренние методы обратного вызова. Внутренние методы обратного вызова - это методы, которые определены в классе сущности.Например, следующий класс сущности определяет все поддерживаемые методы обратного вызова с пустыми реализациями:

@Entity
public static class MyEntityWithCallbacks {
    @PrePersist void onPrePersist() {}
    @PostPersist void onPostPersist() {}
    @PostLoad void onPostLoad() {}
    @PreUpdate void onPreUpdate() {}
    @PostUpdate void onPostUpdate() {}
    @PreRemove void onPreRemove() {}
    @PostRemove void onPostRemove() {}
}

Внутренние методы обратного вызова всегда должны возвращать void и не принимать аргументов.Они могут иметь любое имя и любой уровень доступа (открытый, защищенный, пакетный и частный), но не должны быть статическими.

Аннотация указывает, когда вызывается метод обратного вызова:

@PrePersist - before a new entity is persisted (added to the EntityManager).
@PostPersist - after storing a new entity in the database (during commit or flush).
@PostLoad - after an entity has been retrieved from the database.
@PreUpdate - when an entity is identified as modified by the EntityManager.
@PostUpdate - after updating an entity in the database (during commit or flush).
@PreRemove - when an entity is marked for removal in the EntityManager.
@PostRemove - after deleting an entity from the database (during commit or flush).

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

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

Ограничения реализации Чтобы избежать конфликтов с исходной операцией базы данных, которая инициирует событие жизненного цикла объекта (которое все еще выполняется), методы обратного вызова не должны вызывать методы EntityManager или Query и не должны обращаться к каким-либодругие объекты сущности.

Если метод обратного вызова выдает исключение в активной транзакции, транзакция помечается для отката, и для этой операции больше не вызывается никаких методов обратного вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...