Spring

스프링 부트 : JPA Auditing 생성시간/수정시간 자동화

흰색기린 2021. 9. 24. 11:37

보통 엔티티에는 해당 데이터의 생성 시간과 수정시간을 포함한다.

 

매번 DB에 삽입하기 전, 갱신하기 전에 날짜 데이터를 등록/수정하는 코드가 여기저기 들어감.

public void savePosts(){
	...
    posts.setCreateDate(new LocalDate());
    postsRepository.save(posts);
    ...
}

이 문제를 해결하고자 JPA Auditing를 사용


LocalDate 사용

여기서부터는 날짜 타입 사용.

Java8부터 LocalDate와 LocalDateTime이 등장했습니다.

그간 Java의 기본 날짜 타입인 Date의 문제점을 제대로 고친 타입이라 Java8일 경우 무조건 써야 한다고 생각하면 됨.

 

Java8이 나오기 전 Date와 Calendar 클래스는 문제점이 있었음.

1. 불변(변경이 불가능한)객체가 아닙니다.
 - 멀티스레드 환경에서 언제든 문제가 발생할 수 있음.

2. Calendate는 월 (Month) 값 설계가 잘못되었습니다.
 - 10월을 나타내는 Calendar.OCTOBER의 숫자 값은 '9'입니다.

 

LocalDate와 LocalDateTime이 데이터베이스에 제대로 매핑되지 않는 이슈가 Hibernate 5.2.10 버전에서 해결되었음.

domain 패키지에 BaseTimeEntity 클래스를 생성

 

package com.goodee.cando.domain;

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 BaseTimeEntity {

    @CreatedDate
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime modifiedDate;
}

BastTimeEntity 클래스는?

모든 Entitiy의 상위 클래스가 되어 Entity들의 createdDate, modifiedDate를 자동으로 관리하는 역할

 

@MappedSuperclass

- JPA Entity 클래스들이 BaseTimeEntity을 상속할 경우 필드를 (createdDate, modifiedDate)도

 칼럼으로 인식하도록 합니다.

 

@CreatedDate

- Entity가 생성되어 저장될 때 시간이 자동 저장됩니다.

 

@LastModifiedDate

- 조회한 Entity의 값을 변경할 때 시간이 자동 저장됩니다.

 

그리고 Posts 클래스가 BaseTimeEntity를 상속받도록 변경

 

마지막으로 JPA Auditing 어노테이션들을 모두 활성화할 수 있도록 

Application 클래스에 활성화 어노테이션 하나를 추가하겠습니다.

 

    @Test
    public void BaseTimeEntity_register(){
        //given
        LocalDateTime now = LocalDateTime.of(2021,9,24,0,0,0);
        postsRepository.save(Posts.builder()
                .title("title")
                .content("content")
                .author("author")
                .build());

        //when
        List<Posts> postsList = postsRepository.findAll();

        //then
        Posts posts = postsList.get(0);

        System.out.println(">>>>>>>> createDate="+posts.getCreatedDate()+
                ", modifiedDate="+posts.getModifiedDate());

        assertThat(posts.getCreatedDate()).isAfter(now);
        assertThat(posts.getModifiedDate()).isAfter(now);
    }

테스트 메소드

 

앞으로 추가될 엔티티들은 더 이상 등록일/수정일로 고민할 필요 없음.

BaseTimeEntity만 상속받으면 자동으로 해결되기 때문.