Programming/Spring Boot

JPA @CreatedDate @LastModifiedDate 생성 시간, 수정 시간이 저장되는 원리

Jan92 2021. 11. 6. 01:41

@CreatedDate, @LastModifiedDate

 

@CreatedDate, @LastModifiedDate

 

데이터를 저장할 때 '생성된 시간 정보''수정된 시간 정보'는 여러모로 많이 사용되고 또 중요합니다.

JPA를 사용하면서 @CreatedDate, @LastModifiedDate를 사용하여 생성된 시간 정보, 수정된 시간 정보를 자동으로 저장할 수 있는데요.

 오늘 작업 중에 createAt, updatedAt 값이 계속 null로 들어가던 문제를 해결하면서 동작 원리에 대해 조금 더 살펴본 내용을 정리합니다.

(null이 들어간 원인은 main method가 실행되는 Application class에 @EnableJpaAuditing 어노테이션을 적용하지 않아서였습니다.)

 

 

* 내용 중 자주 등장할 'audit' 는 심사, 감사하다는 뜻입니다.

 

 


 

 

import lombok.Getter;
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;

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTime {

    @CreatedDate
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime modifiedDate;
}

 

많은 테이블에서 공통적으로 사용될 컬럼인 생성된 시간과 수정된 시간을 필드로 가진 BaseTime Class입니다.

대부분의 테이블에서 공통적으로 사용될 컬럼이니만큼 각각의 Entity에 생성하는 것보다 부모 클래스로 만들어 상속받아서 사용하는 것이 효율적이라 그렇게 많이 사용되고 있습니다.

 

 

@MappedSuperclass

해당 어노테이션은 객체의 입장에서 '생성 시간', '수정 시간' 같은 공통 매핑 정보가 필요할 때 사용됩니다.

@MappedSuperclass 어노테이션을 사용함으로써 JPA Entity 클래스들이 BaseTime class를 상속할 경우 BaseTime class의 필드인 createdDate, modifiedDate를 인식하도록 합니다.

 

* @MappedSupperclass가 선언된 클래스는 Entity가 아니며 직접 생성해서 사용될 일이 없기 때문에 대부분 추상 클래스로 만들어집니다. 

(위 BaseTime class도 public abstract class BaseTime으로 만드는 것이 원리적으로는 더 맞습니다.)

 

 

=> 결론적으로 부모 클래스를 상속받는 자식 클래스에게 매핑 정보만을 제공하고 싶을 때 사용하는 어노테이션입니다.

 

 

 

 

@EntityListeners

@EntityListeners

EntityListeners란 JPA Entity에서 이벤트가 발생할 때마다 특정 로직을 실행시킬 수 있는 어노테이션입니다.

 

"Specifies the callback listener classes to be used for an entity or mapped superclass. This annotation may be applied to an entity class for mapped superclass."

(엔티티 클래스 또는 매핑된 슈퍼 클래스에 적용되며, 콜백될 클래스를 지정하는 어노테이션)

 

@EntityListeners(AuditingEntityListener.class) 즉, AuditingEntityListener 클래스가 callback listener로 지정되어 Entity에서 이벤트가 발생할 때마다 특정 로직을 수행하게 됩니다. 

 

 

 

 

AuditingEntityListener class 내부 메서드

AuditingEntityListener class

해당 클래스에 있는 touchForCreate(), touchForUpdate() 메서드입니다. 

 

"Set modification and creation date and auditor on the target object in case it implements Auditable on update events."

(대상 개체에 업데이트 이벤트가 일어나는 것을 auditing 하도록 설정된 경우에 생성된 날짜, 수정된 날짜, 생성자를 저장할 수 있도록 활성화)

 

 

@PrePersist: 해당 엔티티를 저장하기 전

@PreUpdate: 해당 엔티티를 업데이트 하기 전

 

+ 추가로

 

@PostLoad: 해당 엔티티를 새로 불러오거나 refresh 한 이후

@PostPersist: 해당 엔티티를 저장한 이후

@PostUpdate: 해당 엔티티를 업데이트 한 이후

@PreRemove: 해당 엔티티를 삭제하기 전

@PostRemove: 해당 엔티티를 삭제한 이후

 

 

 

 

그리고 결과적으로 

@CreatedDate 어노테이션으로 인해 Entity가 생성되어 저장될 때 시간이 자동으로 저장되고, 마찬가지 @LastModifiedDate는 조회한 Entity의 값을 변경할 때 시간이 자동으로 저장되게 됩니다.

 

 

 

main class

마지막으로 빼먹으면 안되는 @EnableJpaAuditing

어플리케이션의 main method가 있는 클래스에 적용하며 JPA Auditing(감시, 감사) 기능을 활성화하기 위한 어노테이션입니다. 해당 어노테이션을 적용함으로써 createdDate, modifiedDate처럼 DB에 데이터가 저장되거나 수정될 때 언제, 누가 했는지를 자동으로 관리할 수 있게 됩니다.