Back-End/Springboot와 AWS로 혼자 구현하는 웹 서비스

Chapter 03. SpringBoot에서 JPA로 데이터베이스 다뤄보자 (5)

yeonx 2022. 3. 14. 01:42
728x90

3.5 JPA Auditing으로 생성시간/수정시간 자동화하기

 

  • 보통 엔티티에는 해당 데이터의 생성시간과 수정시간을 포함
  • 언제 만들어졌는지, 언제 수정되었는지 등은 유지보수에 있어 굉장히 중요한 정보이기 때문
  • 그렇다 보니 매번 DB에 삽입하기 전, 갱신하기 전에 날짜 데이터를 등록/수정하는 코드가 여기저기 들어가게 됨
// 생성일 추가 코드 예제
public void savePosts(){
    ...
    posts.setCreateDate(new LocalDate());
    postsRepository.save(posts);
    ...
}

이런 단순하고 반복적인 코드가

모든 테이블과 서비스 메소드에 포함되어야 한다고 생각하면

어마어마하게 귀찮고 코드가 지저분해짐

-> 해결책으로 JPA Auditing을 사용


LocalDate 사용

여기서부터는 날짜 타입을 사용 - Java의 기본 날짜 타입인 Date의 문제점을 제대로 고친 타입 : 무조건 쓰자!

 

 💡 참고 💡
Java8이 나오기 전까지 사용되었던 Date와 Calendar 클래스는 다음과 같은 문제점들이 있었음.
1. 불변(변경이 불가능한) 객체가 아님
- 멀티스레드 환경에서 언제든 문제가 발생할 수 있음.
2. Calendar는 월(Month) 값 설계가 잘못됨
- 10월을 나타내는 Calendar.OCTOBER의 숫자 값은 '9'임
Joda Time이라는 오픈소스를 사용해서 문제점들을 피했었고, Java8에선  LocalDate를 통해 해결

-> 사용법 : domain 패키지에 BaseTimeEntity 클래스를 생성

 

BaseTimeEntity클래스는 모든 Entity의 상위 클래스가 되어

Entity들의 createdDate, modifiedDate를 자동으로 관리하는 역할

 

BaseTimeEntity.java

package com.jojoldu.book.springboot.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;
    
}
① @MappedSuperclass
 - JPA Entity 클래스들이 BaseTimeEntity을 상속할 경우 필드들(createdDate, modifiedDate)도 칼럼으로 인식하도록 함.

② @EntityListeners(AuditingEntityListener.class)
 - BaseTimeEntity 클래스에 Auditing 기능을 포함시킴

③ @CreatedDate
 - Entity가 생성되어 저장될 때 시간이 자동으로 저장됨

④ @LastModifiedDate
 - 조회한 Entity의 값을 변경할 때 시간이 자동 저장됨

 

 

Posts 클래스가 BaseTimeEntity를 상속받도록 변경해주기

 

Posts.java

	...
public class Posts extends BaseTimeEntity {
	...
}

 

 

JPA Auditing 어노테이션들을 모두 활성화할 수 있도록 Application 클래스에 활성화 어노테이션 추가

 

Application.java

@EnableJpaAuditing // JPA Auditing 활성화
@SpringBootApplication
public class Application { //앞으로 만들 프로젝트의 메인 클래스
    public static void main(String[] args){
        SpringApplication.run(Application.class,args);
    }
}

JPA Auditing 테스트 코드 작성하기

 

PostsRepositoryTest.java

@Test
public void BaseTimeEntity_등록(){

    //given
    LocalDateTime now = LocalDateTime.of(2019,6,4,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);
}

 

테스트 코드를 수행해 보면 다음과 같이 실제 시간이 잘 저장된 것을 확인할 수 있음

JPA Auditing 테스트 코드 결과

 

등록일/수정일로 고민할 필요가 없음

BaseTimeEntity만 상속받으면 자동으로 해결

 

출처 : 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 [이동욱 지음]