본문 바로가기
JPA

JPA - Entity Listener

by sinabeuro 2022. 3. 25.
728x90

JPA에서 제공하는 Entity Listener의 종류와 쓰임에 대해서 정리해보았습니다.

Entity Listener는 JPA가 동작하는 이벤트 구간을 관찰하고 있다가 발생하면 특정 동작을 실행하는 메소드라고 볼 수 있습니다.

 

Entity Listener Annotation

@PrePersist: entity manager persist operation(insert 작업)가 실행되기 전

@PreRemove: entity manager remove operation(delete 작업)가 실행되기 전
@PreUpdate: database의 update 작업이 실행되기 전

@PostPersist: database의 insert 작업이 실행된 이후

@PostRemove: database의 delete 작업이 실행된 이후
@PostUpdate: database의 update 작업이 실행된 이후
@PostLoad: select 조회가 된 직후

 

즉 Entity Listener는 데이터 베이스의 DML 쿼리 동작의 전후 시점에 이벤트를 발생시킬 수 있게 해준다.

예를 들면, insert 직전에 생성일을 만들어주거나, update 직후에 수정일을 만들어서 쿼리에 해당 값을 넣어주는 것이다.

주의할 점은 같은 Entity 내에 같은 Entity Listener를 만들면 안됩니다!!

 

Entity Listener를 Entity 내부에 마다 직접적으로 다 선언해서 사용하는 것이 아니라,

공통 기능으로 사용할 수 있습니다. 

JPA Entity 프로퍼티를 공통적으로 사용하면서 해당 프로퍼티에 공통적으로 Entity Listener를 구현함으로써, 코드를 좀 더 간결하고 일괄되게 작성할 수 있습니다.

이러한 기능을 구현하기 위해서는 클래스 상속 외에도 몇가지 어노테이션을 사용해서 구현해야합니다.

 

 

 

Entity Listener 단일 클래스 내부에서 구현

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Data
@NoArgsConstructor
@Entity
public class User {

    @Id
    @GeneratedValue
    private Long id;

    private Long userId;

    private String name;

    private String email;
    
    private LocalDateTime createdAt;
    
    private LocalDateTime updatedAt;
    
    @PrePersist
    public void prePersist() {
        System.out.println(">>> prePersist");
    }

    @PostPersist
    public void postPersist() {
        System.out.println(">>> postPersist");
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }

    @PreUpdate
    public void preUpdate() {
        System.out.println(">>> preUpdate");
    }

    @PostUpdate
    public void postUpdate() {
        System.out.println(">>> postUpdate");
        this.updatedAt = LocalDateTime.now();
    }

}

해당 클래스 내부에서만 Entity Listener를 사용할 경우,

클래스 내부에 Entity Listener 어노테이션을 사용하여 메소드로 구현하면 됩니다.

 

 

 

 

JPA의 Auditing 기능

JPA의 Auditing 기능을 사용하서 Entity Listener를 공통 모듈로 구현할 수 있습니다.

Audit은 주로 DB값이 변경했을 때 누가 값을 변경했고, 언제 변경했는지 Audit(감사)하는 용도로 합니다.

Spring Data JPA는 @CreatedDate, @LastModifiedDate, @CreatedBy, @LastModifiedBy 와 같은 어노테이션을 제공합니다.

 

Auditing 기능을 사용해서 Entity Listener를 공통 클래스로 구현하기 위해서는 몇 가지 작업이 필요합니다.

@SpringBootApplication
@EnableJpaAuditing
public class FastJpaApplication {

    public static void main(String[] args) {
        SpringApplication.run(FastJpaApplication.class, args);
    }

}

우선 메인 클래스에 @EnableJpaAuditing를 선언합니다.

 

package com.example.bookmanager.domain;

import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@Data
@MappedSuperclass   // 해당 클래스의 필드를 상속받는 class의 Entity 컬럼으로 추가시키겠다는 뜻
@EntityListeners(value = AuditingEntityListener.class)
public class BaseEntity {

    @CreatedDate
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime updatedAt;
}

상속받아 사용할 공통 프로퍼티를 담은 클래스를 만들어줍니다.

@MappedSuperclass 어노테이션은 해당 클래스를 상속받는 자식클래스에 부모 프로퍼티를 Entity 컬럼으로 사용할 수 있게 하는 기능을 합니다.

@EntityListeners(value = AuditingEntityListener.class) 어노테이션은 다른 클래스에 등록되어 있는 Entity listener를 사용하게 합니다. 

사용자 Entity listener가 존재한다면, @EntityListeners의 value 값으로 등록해서 사용하면 됩니다.

여기에서는 Auditng에 정의된 Entity listener를 사용함으로, AuditingEntityListener.class를 @EntityListeners의 value 값으로 지정해주시면 됩니다.

 

공통 클래스 내에 프로퍼티에 Autiting 어노테이션을 사용합니다.

날짜는 생성해주는 @CreatedDate, @LastModifiedDate 를 사용하면 insert, update 시 자동으로 현재 날짜를 생성해줍니다.

@CreatedBy, @LastModifiedBy 는 각각 생성자, 수정자를 등록할 수 있게 하는 어노테이션입니다. 

@CreatedBy, @LastModifiedBy 어노테이션은 주로 스프링 시큐리티의 Principal과 함께 사용합니다.

이후 포스팅에 스프링 시큐리티와 같이 다루어 보기로 하겠습니다.

 

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Data
@ToString(callSuper = true)     // 상속 받는 클래스의 프로퍼티를 정상적으로 등록하기 위한 추가 처리
@EqualsAndHashCode(callSuper = true) // 상속 받는 클래스의 프로퍼티를 정상적으로 등록하기 위한 추가 처리
@NoArgsConstructor
@Entity
public class User extends BaseEntity  {

    @Id
    @GeneratedValue
    private Long id;

    private Long userId;

    private String name;

    private String email;

}

마지막으로 공통 기능을 사용할 본 Entity에서 공통 Entity Listener를 구현한 BaseEntity 클래스를 상속받으면 됩니다.

주의할 점은 상속받은 프로퍼티를 정상적으로 사용하기 위해서

@ToString(callSuper = true), @EqualsAndHashCode(callSuper = true)  와 같은 추가 처리를 꼭 하셔야합니다.

이로써, BaseEntity 클래스에 구현한 createdAt, updatedAt 프로퍼티를 정상적으로 사용할 수 있게 되며, 해당 프로퍼티에 구현되어있는 Autiting Entity Listener를 사용할 수 있게 됩니다.

 

Entity Listener 예제에 관해서는 다음 포스팅에서 한번 더 다룰 예정입니다.

여기까지 끊고 마무리하겠습니다.

 

 

 

 

 

 

 

https://docs.jboss.org/hibernate/core/4.0/hem/en-US/html/listeners.html

 

Chapter 6. Entity listeners and Callback methods

@PostPersistExecuted after the entity manager persist operation is actually executed or cascaded. This call is invoked after the database INSERT is executed.

docs.jboss.org

 

https://milenote.tistory.com/79

 

[ JPA ] 4. Entity Listener

Reference. 한 번에 끝내는 Java/Spring 웹 개발 마스터 초격차 패키지 Online 이전 글 더보기 1. Repository interface 메서드 2. Query Method 정의 및 실습 3, Entity 기본속성 5.5. Entity Listener Listener:..

milenote.tistory.com

 

https://umanking.github.io/2019/04/12/jpa-audit/

 

[JPA] Auditing 사용하기

Spring Data JPA의 Audit 기능에 대해서 알아보자.

umanking.github.io

 

728x90

'JPA' 카테고리의 다른 글

JPA - 트랜잭션 매니저1 개요  (0) 2022.03.25
JPA - 트랜잭션 매니저2 독립성(격리) 속성  (0) 2022.03.25
JPA - 연관 관계  (0) 2022.03.25
JPA - Entity의 기본 속성  (0) 2021.12.03
JPA - JPA 관련 용어 소개  (0) 2021.11.30

댓글