Аннотация | Описание |
---|---|
@PrePersist | Помечает метод для вызова до выполнения EntityManager.persist() |
@PostPersist | Помечает метод для вызова после того, как будет обеспечено постоянство сущности. Если сущность будет автоматически генерировать свой первичный ключ (с использованием @GeneratedValue), то значение окажется доступно в соответствующем методе |
@PreUpdate | Помечает метод для вызова до выполнения операции обновления в отношении базы данных (путем вызова сеттеров сущности или метода EntityManager.merge()) |
@PostUpdate | Помечает метод для вызова после выполнения операции обновления в отношении базы данных |
@PreRemove | Помечает метод для вызова до выполнения EntityManager.remove() |
@PostRemove | Помечает метод для вызова после того, как сущность будет удалена |
@Postload | Помечает метод для вызова после того, как сущность будет загружена (посредством JPQL-запроса или EntityManager.find()) либо обновлена из основной базы данных. Аннотации @Preload не существует, поскольку в предварительной загрузке данных для сущности, которая еще не создана, нет смысла |
Результатом добавления аннотаций обратных вызовов в UML-диаграмму состояний, показанную на рис. 6.6, является диаграмма, которую можно увидеть на рис. 6.7.
Перед вставкой сущности в базу данных менеджер сущностей вызывает метод, снабженный аннотацией @PrePersist. Если вставка не приведет к генерированию исключения, то будет обеспечено постоянство сущности, инициализирован ее идентификатор, а затем вызван метод, снабженный аннотацией @PostPersist. Аналогичное поведение наблюдается при операциях обновления (@PreUpdate, @PostUpdate) и удаления (@PreRemove, @PostRemove). Метод, аннотированный с использованием @PostLoad, вызывается после загрузки сущности из базы данных (посредством EntityManager.find() или JPQL-запроса). Когда сущность отсоединяется и требуется произвести ее слияние, менеджер сущностей сначала должен проверить, имеются ли какие-либо отличия от информации, содержащейся в базе данных (@PostLoad). Если да, то ему надлежит обновить данные (@PreUpdate, @PostUpdate).
Рис. 6.7. Жизненный цикл сущности с аннотациями обратных вызовов
Как все это выглядит в коде? Сущности могут включать не только атрибуты, конструкторы, геттеры и сеттеры, но и бизнес-логику, используемую для валидации их состояния или выполнения вычислений для некоторых их атрибутов. Сюда могут входить обычные Java-методы, вызываемые другими классами, или аннотации обратных вызовов (которые также называются методами обратного вызова), как показано в листинге 6.38. Менеджер сущностей вызывает их автоматически в зависимости от инициируемого события.
@Entity
public class Customer {
··@Id @GeneratedValue
··private Long id;
··private String firstName;
··private String lastName;
··private String email;
··private String phoneNumber;
··@Temporal(TemporalType.DATE)
··private Date dateOfBirth;
··@Transient
··private Integer age;
··@Temporal(TemporalType.TIMESTAMP)
··private Date creationDate;
··@PrePersist
··@PreUpdate
··private void validate() {
····if (firstName == null || "".equals(firstName))
······throw new IllegalArgumentException("Неверное имя");
····if (lastName == null || "".equals(lastName))
······throw new IllegalArgumentException("Неверная фамилия");
··}
··@PostLoad
··@PostPersist
··@PostUpdate