Search
Duplicate
👂🏻

JPA Entity 이벤트 및 리스너 알아보기

글감
BE
Spring
Java
작성자
작성 일자
2023/12/08 10:36
상태
완료
공개여부
공개
Date
생성자
작업자

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
복사

참고