1HOON
논리적 코딩
1HOON
전체 방문자
오늘
어제
  • HOME (187)
    • ☕️ JAVA (28)
      • WhiteShip Java LIVE Study (6)
      • Effective JAVA (10)
    • 🔮 KOTLIN (4)
    • 🌱 SPRING (51)
      • 스프링 인 액션 (22)
      • JPA (18)
    • ☕️ JAVASCRIPT (6)
    • 📃 DATABASE (40)
      • ORACLE (37)
      • MSSQL (2)
    • 🐧 LINUX (4)
    • 🐳 DOCKER (5)
    • 🐙 KUBERNETES (4)
    • 🏗️ ARCHITECTURE (8)
    • 📦 ETC (27)
      • TOY PROJECT (5)
      • RECRUIT (1)
      • 그냥 쓰고 싶어서요 (14)
      • TIL (1)
    • 🤿 DEEP DIVE (1)
    • 🚽 Deprecated (9)
      • PYTHON (3)
      • AWS (2)
      • HTTP 완벽가이드 (3)
      • WEB (1)

블로그 메뉴

  • 홈
  • 방명록
  • 관리

인기 글

최근 글

티스토리

hELLO · Designed By 정상우.
1HOON

논리적 코딩

[Spring Data JPA] Auditing에 ZonedDateTime 사용하기
🌱 SPRING/JPA

[Spring Data JPA] Auditing에 ZonedDateTime 사용하기

2021. 5. 27. 00:56

 

들어가며


JPA에는 엔티티의 생성 일자와 최종 수정일자, 생성자와 최종 수정자를 entityManager에서 persist하기 전에 자동으로 현재 일시로 세팅해주는 기능이 존재합니다. JPA Auditing이라고 하는데요, 대부분의 경우 이 Auditing 기능을 @MappedSuperclass로 만들고 엔티티 클래스에서 상속받도록 구현합니다.

 

이번 포스팅은 이 JPA Auditing 중 생성 일자와 최종 수정일자 필드의 타입에 관한 포스팅입니다.

 

 

문제가 뭐였냐면


프로젝트의 날짜 타입을 ZonedDateTime으로 통일함에 따라, Auditing의 @CreatedDate와 @LastModifiedDate 필드 또한 ZonedDateTime으로 변경하게 되었습니다.

 

단순히 필드의 자료형만 변경하면 될 줄 알았는데, 이게 왠걸? @CreatedDate와 @LastModifiedDate는 ZonedDateTime 타입을 지원하지 않았습니다.

 

 

AuditAware not converting to ZonedDateTime anymore [DATAJPA-1242] · Issue #1579 · spring-projects/spring-data-jpa

Hetmoteus opened DATAJPA-1242 and commented I am using spring-boot 1.5.x with @EnableJpaAuditing My entity has the following attribute : @CreatedDate protected ZonedDateTime createdAt; It was worki...

github.com

 

좀 오래된 이슈이긴 하지만, Jens Schauder에 따르면 ZonedDateTime 지원 시, 디폴트 타임존을 어디로 지정할 지 결정할 수 없기 때문에 지원하지 않는다고 합니다.(제가 잘못본것일수있어요)

 

그래서 해당 필드들만 LocalDateTime으로 둘까 하다가 좀 더 공부해서 해결했습니다.

아래는 변경 전 @MappedSuperclass 입니다.

 

@Getter
@MappedSuperclass
public abstract class LogEntity {
	@CreatedDate
    private LocalDateTime createDate;
    
    @LastModifiedDate
    private LocalDateTime updateDate;
}

 

 

해결 방법


JPA에서는 EntityListener로서 @PrePersist와 @PreUpdate를 제공합니다. 각각 엔티티가 INSERT/UPDATE 되기 전에 원하는 메서드를 실행시켜주는 기능을 합니다.

 

그래서 저는 이 기능을 @CreatedDate와 @LastModifiedDate 대신 사용하기로 했습니다.

 

@Getter
@MappedSuperclass
public abstract class LogEntity {
    private ZonedDateTime createDate;
    private ZonedDateTime updateDate;

    @PrePersist
    public void prePersist() {
        this.createDate = ZonedDateTime.now();
        this.updateDate = ZonedDateTime.now();
    }

    @PreUpdate
    public void preUpdate() {
        this.updateDate = ZonedDateTime.now();
    }
}

 

엔티티 저장 시

@PrePersist 어노테이션이 붙은 prePersist() 메서드가 실행되고, LogEntity를 상속받는 엔티티의 createDate와 updateDate 필드에 현재 일시를 세팅해주고 저장합니다.

 

엔티티 수정 시

@PreUpdate 어노테이션이 붙은 preUpdate() 메서드가 실행되고, LogEntity를 상속받는 엔티티의 updateDate 필드에 현재 일시를 세팅해주고 수정합니다.

 

 

 

테스트 코드


JUnit5로 아래 코드를 통해 생성일시와 수정일시 필드의 값 세팅이 정상적인지 확인했는데, 모두 정상적이었습니다.

 

@SpringBootTest
class ZoneEntityRepositoryTest {
    @Autowired
    ZoneEntityRepository zoneEntityRepository;

    @Test
    void 로그필드_세팅_확인() {
        // given
        ZoneEntity entity = new ZoneEntity();
        entity.setName("name");

        // when
        ZoneEntity savedEntity = zoneEntityRepository.save(entity);

        // then
        assertNotNull(savedEntity.getCreateDate());
        assertNotNull(savedEntity.getUpdateDate());

        System.out.println(savedEntity.getCreateDate().toString());
        System.out.println(savedEntity.getUpdateDate().toString());
    }

    @Test
    void 수정일자_갱신_확인() {
        // given
        ZoneEntity entity = new ZoneEntity();
        entity.setName("name");

        // when
        ZoneEntity savedEntity = zoneEntityRepository.save(entity);
        savedEntity.setName("updated");
        ZoneEntity updatedEntity = zoneEntityRepository.save(savedEntity);

        // then
        assertNotNull(updatedEntity.getCreateDate());
        assertNotNull(updatedEntity.getUpdateDate());
        assertNotEquals(savedEntity.getUpdateDate(), updatedEntity.getUpdateDate());

        System.out.println(updatedEntity.getCreateDate().toString());
        System.out.println(updatedEntity.getUpdateDate().toString());
    }
}

 

반응형
저작자표시 비영리 변경금지 (새창열림)

'🌱 SPRING > JPA' 카테고리의 다른 글

[QueryDSL] JPA에서 MySQL 비트연산하는 방법  (0) 2022.07.15
[JPA] 즉시 로딩/지연 로딩  (0) 2020.07.29
[JPA] 프록시  (2) 2020.07.29
[JPA] 상속관계 매핑  (0) 2020.07.19
[JPA] 다양한 연관관계 매핑  (0) 2020.07.19
    '🌱 SPRING/JPA' 카테고리의 다른 글
    • [QueryDSL] JPA에서 MySQL 비트연산하는 방법
    • [JPA] 즉시 로딩/지연 로딩
    • [JPA] 프록시
    • [JPA] 상속관계 매핑
    1HOON
    1HOON

    티스토리툴바