티스토리 뷰

반응형

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

보통 Entity는 해당 데이터의 생성시간과 수정시간을 포함하고 있다. 이런 정보는 추후 유지보수에 있어 굉장히 중요한 정보이기 때문이다. 이렇다 보니 DB에 삽입 및 갱신할 때는 날짜 데이터를 등록/수정하는 코드가 항상 들어가게 된다.

//Ex. 생성일 추가
public void savePosts() {
  ...
  posts.setCreateDate(new LocalDate());
  postsRepository.save(posts);
  ...
}

하지만 이런 코드가 모든 테이블과 서비스 메소드에 구현해야하 한다면 중복이 발생하고 코드가 지저분해진다는 점이 발생하게 된다. 이런 문제를 해결하고자 나타난 것이 JPA Auditing이다.

 

 

LocalDate 사용

Java8 부터 LocalDate와 LocalDateTime이 등장했다. 그간 Java의 기본 날짜 타입인 Date의 문제점을 제대로 고친 타입이라 Java8일 경우 무조건 써야한다.

Java Date의 문제점

Java8이 나오기 전 Date와 Calendar 클래스는 다음과 같은 문제점이 있다.

  1. 불변(변경 가능한)객체가 아니다.
    • 즉, 멀티스레드 환경에서 문제가 발생할 수 있다.
  2. Calendar는 월(month) 값 설계가 잘못되었다.
    • 10월을 나타내는 Calendar.OCTOBER의 숫자 값은 '9'이다.
    • 당연히 '10'으로 생각한 개발자는 크게 당황할 것이다.

이런 문제점을 피하기 위해 JodaTime이라는 오픈소스를 사용해서 문제점을 피했었고, Java8에선 LocalDate를 통해 해결했다.

자세한 내용! https://d2.naver.com/helloworld/645609

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

 

그럼 이제 domain 패키지에 BaseTimeEntity 클래스를 생성하자.

image

 

BaseTimeEntity

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity {
    @CreatedDate
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime modifiedDate;
}

BaseTimeEntity 클래스는 모든 Entity의 상위 클래스가 되어 Entity들의 createdDate와 modifiedDate를 자동으로 관리하는 역할을 하는 것이다.

 

어노테이션에 대해 간단히 설명하면,

  • @MappedSuperclass
    • JPA Entity 클래스들이 BaseTimeEntity을 상속할 경우 필드들(createdDate, modifiedDate)도 컬럼으로 인식하도록 한다.
  • @EntityListeners(AuditingEntityListener.class)
    • BaseTimeEntity 클래스에 Auditing 기능을 포함시킨다.
  • @CreatedDate
    • Entity가 생성되어 저장될 때 시간이 자동 저장된다.
  • @LastModifiedDate
    • 조회한 Entity의 값을 변경할 때 시간이 자동 저장된다.

그럼 이제 Posts의 클래스(Entity 클래스)가 BaseTimeEntity를 상속받도록 변경하자.

public class Posts extends BaseTimeEntity {
  ...
}

이제 마지막으로 JPA Auditing 어노테이션들을 모두 활성화할 수 있도록 Application 클래스에 활성화 어노테이션을 추가하겠다.

@EnableJpaAuditing    //JPA Auditing 활성화
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

 

자 이제 코드가 완성되었으니, 테스트를 작성해보도록 하자.

PostsRepositoryTest

@RunWith(SpringRunner.class)
@SpringBootTest
public class PostsRepositoryTest {

    @Autowired
    PostsRepository postsRepository;

    @After
    public void cleanup() {
        postsRepository.deleteAll();
    }

    ...

    @Test
    public void insertBaseTimeEntity() {
        //given
        LocalDateTime now = LocalDateTime.now();
        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);
    }
}

스크린샷 2020-11-18 오후 10 00 49

테스트 코드를 실행해보면 다음과 같이 실제시간이 잘 저장된 것을 확인할 수 있다. 즉, save()할 때 title, content, author만 설정했는데 JPA Auditing로 인해 시간까지 같이 저장된 것이다.

 

앞으로 추가될 엔티티들은 더 이상 등록일/수정일에 대해 고민할 필요 없이 그저 BaseTimeEntity만 상속받으면 자동으로 해결된다.

스프링 부트와 AWS로 혼자 구현하는 웹 서비스
국내도서
저자 : 이동욱
출판 : 프리렉 2019.11.29
상세보기

 

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함