TIL(Today I Learned)

TIL - ZonedDateTime 사용 시 Converter로 DB와의 시간 차 해결

Happy._. 2024. 7. 22. 22:18

이번 프로젝트에서 LocalDateTime 대신 ZonedDateTime을 사용하면서 DB에 저장 전, 후의 시간 차가 발생했다.

 

DB에 저장 전 데이터를 보면 Asia/Seoul 기준이지만, DB에 저장된 데이터를 보면 UTC 기준이다.

해당 데이터로 시간을 비교하려면 시간 차까지 한 번 더 고려해야 했다.

 

ZoneId.of("Asia/Seoul")로 명시적으로 타임존을 설정해도 DB에 저장될 때는 타임존 부분은 제외된다.

 

이 문제를 해결하기 위해 util 패키지에 다음과 같이 코드를 추가했다.

@Converter(autoApply = true)
class ZonedDateTimeConverter : AttributeConverter<ZonedDateTime, Timestamp> {

    override fun convertToDatabaseColumn(attribute: ZonedDateTime?): Timestamp? =

        attribute?.let { Timestamp.from(it.toInstant()) }

    override fun convertToEntityAttribute(dbData: Timestamp?): ZonedDateTime? =

        dbData?.toInstant()?.atZone(ZoneId.systemDefault())
}
  • AttributeConverter<Entity Field Type, DB Column Type>:
    • JPA의 일부로, 엔티티 속성 상태를 데이터베이스 열 표현으로 변환하고 다시 엔티티 속성으로 변환하는 데 사용
    • DB에 INSERT 하기 전과 SELECT 할 때 자동으로 값을 변환해 줌
    • EX) <ZonedDateTime, Timestamp>: ZonedDateTime 객체를 Timestamp 객체로 변환 / 역변환
  • @Converter(autoApply = true): ZonedDateTime 타입의 모든 엔티티 속성에 자동으로 적용
    • @Convert(converter = AttributeConverter를 구현한 클래스명.class): 개별 적용 시 적용할 Entity의 프로퍼티에 적용
  • convertToDatabaseColumn: DB에 INSERT 전 수행
  • convertToEntityAttribute: SELECT 할 때, Entity 필드에 바인딩 할 때 수행