Entity Listener
모든 엔티티를 대상으로 언제 어떤 요청을 했는지 항상 대기하며 기다리는 것은 비효율적이다. 이런 상황에서 JPA의 Entity 이벤트와 리스터 기능을 사용하면, 엔티티의 생명 주기에 따라 이벤트를 처리할 수 있다.
하이버네이트에서는 JPA Entity에 이벤트가 발생할 때 콜백처리를 할 수 있도록 지원해주는 Entity Listener라는 서비스가 있다. 엔티티 리스너는 엔티티 이벤트를 감지하여 콜백함수를 통해 이벤트 전후에 대한 동작을 처리할 수 있다.
Entity 이벤트 종류
Entity 객체의 이벤트는 저장과 수정, 조회, 삭제의 이벤트를 말하며, JPA에서 어노테이션으로 각 이벤트 전후에 동작을 처리할 수 있다.
•
Event 실행 전
◦
@PrePersist
▪
Entity save (insert) 실행되기 전
▪
엔티티를 영속성 컨텍스트에 관리하기 직전에 호출
▪
@GenerateValue를 통해 식별자 생성 전략을 사용한 경우, 엔티티의 식별자는 존재하지 않는 상태이다.
◦
@PreUpdate
▪
Entity save (merge) 실행되기 전
▪
flush나 commit을 호출해 데이터베이스에 엔티티 수정사항을 반영하기 직전에 호출
◦
@PreRemove
▪
Entity delete 실행되기 전
▪
엔티티를 영속성 컨텍스트에서 삭제하기 직전에 호출
▪
영속성 전이가 발생할 때도 호출되며, orphanRemoval에 대해서는 flush나 commit 시에 호출된다.
•
Event 실행 후
◦
@PostPersist
▪
Entity save (insert) 실행되고 난 후
▪
flush나 commit을 호출해 데이터베이스에 엔티티를 저장한 직후 호출
▪
@GenerateValue의 식별자 생정 전략이 IDENTITY인 경우, 식별자를 생성하기 위해 persist()를 호출하면서 해당 엔티티를 데이터베이스에 저장하므로, 이 경우에는 persist()를 호출한 직후에 바로 PostPersist가 호출된다.
◦
@PostUpdate
▪
Entity save (merge) 실행되고 난 후
▪
flush나 commit을 호출해 데이터베이스에 엔티티 수정사항이 반영된 직후에 호출
▪
persist() 호출 시에는 동작하지 않는다.
◦
@PostRemove
▪
Entity delete 실행되고 난 후
▪
flush나 commit을 호출해서 엔티티를 데이터베이스에 삭제한 직후 호출
◦
@PostLoad
▪
Entity find 실행되고 난 후
▪
엔티티가 영속성 컨텍스트에 조회된 직후나 refresh 직후 호출
이벤트 적용 방법
1.
엔티티에 직접 적용
@Getter
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
@PostLoad
public void postLoad() {
System.out.println("PostLoad");
}
@PrePersist
public void prePersist() {
System.out.println("prePersist");
}
@PreUpdate
public void preUpdate() {
System.out.println("PreUpdate");
}
@PreRemove
public void preRemove () {
System.out.println("PreRemove ");
}
@PostPersist
public void postPersist() {
System.out.println("PostPersist ");
}
@PostUpdate
public void postUpdate () {
System.out.println("PostUpdate ");
}
@PostRemove
public void postRemove() {
System.out.println("PostRemove ");
}
}
Java
복사
2.
별도의 리스너 사용
public class Listener {
@PostLoad
public void postLoad(Member obj){
System.out.println("PostLoad obj = "+obj);
}
@PrePersist
public void prePersist(Member obj){
System.out.println("prePersist"+obj);
}
@PreUpdate
public void preUpdate(Object obj){
System.out.println("PreUpdate");
}
@PreRemove
public void preRemove (Object obj){
System.out.println("PreRemove ");
}
@PostPersist
public void postPersist (Object obj){
System.out.println("PostPersist ");
}
@PostUpdate
public void postUpdate (Object obj){
System.out.println("PostUpdate ");
}
@PostRemove
public void postRemove(Object obj){
System.out.println("PostRemove ");
}
}
Java
복사
@Getter
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Entity
@EntityListeners(Listener.class)
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
}
Java
복사