양석 메커니즘 내부에서 발생하는 어떤 이벤트들에 반응하는 것은 어플리케이션에 자주 유용하다. 이것은 어떤 종류의 일반적 기능, 그리고 미리 만들어진 기능의 확장에 대한 구현을 허용해준다. EJB3 명세서는 이 용도를 위한 두 개의 관련된 메커니즘들을 제공한다.
엔티티의 메소드는 하나의 특정한 엔티티 생명 주기 이벤트의 통보를 수신받기 위한 하나의 콜백 메소드로서 고안될 수 있다. 당신은 또한 엔티티 클래스 내부에 직접 정의된 콜백 메소드들 대신에 사용될 하나의 엔티티 리스너 클래스를 정의할 수 있다. 하나의 엔티티 리스너는 아규먼트 없는 생성자를 가진 상태없는 클래스이다. 엔티티 리스너는 엔티티 클래스를 @EntityListener 주해로 엔티티 클래스를 주해함으로써 정의된다:
@Entity(access=FIELD)
@EntityListener(class=Audit.class)
public class Cat {
@Id private Integer id;
private String name;
private Calendar dateOfBirth;
@Transient private int age;
private Date lastUpdate;
//getters and setters
/**
* Set my transient property at load time based on a calculation,
* note that a native Hibernate formula mapping is better for this purpose.
*/
@PostLoad
public void calculateAge() {
Calendar birth = new GregorianCalendar();
birth.setTime(dateOfBirth);
Calendar now = new GregorianCalendar();
now.setTime( new Date() );
int adjust = 0;
if ( now.get(Calendar.DAY_OF_YEAR) - birth.get(Calendar.DAY_OF_YEAR) < 0) {
adjust = -1;
}
age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR) + adjust;
}
}
public class LastUpdateListener {
/**
* automatic property set before any database persistence
*/
@PreUpdate
@PrePersist
public void setLastUpdate(Cat o) {
o.setLastUpdate( new Date() );
}
}동일한 콜백 메소드 또는 엔티티 리스너 메소드는 하나 이상의 콜백 주해들로서 주해될 수 있다. 주어진 하나의 엔티티에 대해, 당신은 그것이 하나의 콜백 메소드이든지 하나의 엔티티 리스너 메소드이든지 간에 동일한 콜백 주해에 의해 주해되는 두 개의 메소드들을 가질 수 없다. 하나의 콜백 메소드는 반환 타입 없이 어떤 임의의 이름을 가진 하나의 아규먼트 없는 메소드이다. 하나의 엔티티 리스너는 시그너처 public void <METHOD>(Object)을 가지며 여기서 Object는 실제 엔티티 타입이다 (Hibernate 엔티티 관리자는 이 생성자를 완화시키고 (몇몇 엔티티들을 가로질러 리스너들을 공유하는 것을 허용하는) java.lang.Object 타입의 Object를 허용함을 노트하라.)
하나의 콜백 메소드는 RuntimeException을 일으킨다. 아무튼 현재 트랜잭션은 롤백되어야 한다. 다음 콜백들이 정의된다:
표 5.1. Callbacks
| 타입 | 설명 |
|---|---|
| @PrePersist | 엔티티 관리자 persist 연산이 실제로 실행되거나 케스케이드 되기 전에 실행된다. 이 호출은 persist 연산과 동기적이다. |
| @PreRemove | 엔티티 관리자 remove 연산이 실제로 실행되거나 케스케이드 되기 전에 실행된다. 이 호출은 remove 연산과 동기적이다. |
| @PostPersist | 엔티티 관리자 persist 연산이 실제로 실행되거나 케스케이드 된 후에 실행된다. 이 호출은 데이터베이스 INSERT가 실행된 후에 호출된다. |
| @PostRemove | 엔티티 관리자 remove 연산이 실제로 실행되거나 케스케이드 된 후에 실행된다. 이 호출은 remove 연산과 동기적이다. |
| @PreUpdate | 데이터베이스 UPDATE 연산 전에 실행된다. |
| @PostUpdate | 데이터베이스 UPDATE 연산 후에 실행된다. |
| @PostLoad | 하나의 엔티티가 현재의 영속 컨텍스트 속으로 로드된 후에 또는 하나의 엔티티가 갱신된 후에 실행된다. |
하나의 콜백 메소드는 EntityManager 메소드나 Query 메소드를 호출하지 말아야 한다!