티스토리 뷰

코프링으로 개발하면서 zeroDateTime(0000-00-00 00:00:00)인 LocalDateTime 값 관련해서 마주한 내용을 포스팅해봤습니다.

배경

as-is(파이썬) 코드로 되어 있는 배치 스크립트를 코틀린으로 이전하는 작업에서 발생했습니다.

as-is 코드에서 사용하지 않는 row는 수정 시간을 zeroDateTime으로 변경해주는 로직이 있었습니다.

SQL문으로 직접 수정해주었기 때문에 별 문제 없는 로직이었습니다.

허나, 스프링 환경에서 적용하려고 하니 다음과 같은 문제가 발생했습니다.

바로 LocalDate 타입에서 month와 day 값의 최소값이 1인 점이었습니다.

import java.time.LocalDate
import java.time.LocalDateTime

fun main() {
    val localDate = LocalDate.of(0, 0, 0)
}

위 코드를 테스트해보아도 다음과 같은 에러가 발생하여 zeroDateTime을 사용하기 어려웠습니다.

해결 방법

[1]. zeroDateTime 사용하지 않기

해결 방법이 사용하지 않기라서 의아하실 수도 있습니다.

하지만 zeroDateTime을 사용하는 건 결코 좋은 방법은 아닙니다.

다양한 이유가 있겠지만, LocalDate에서도 0달 0일을 제공하지 않는 걸로 이유를 들 수 있겠습니다.

spring.datasource.url에서도 zeroDateTIme을 null로 변경해주는 옵션이 있습니다.

url: jdbc:mysql://localhost:3306/cafe?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull

이 옵션이 있으면 데이터베이스에 zeroDateTime으로 저장되어있더라도 null로 가져옵니다.

저도 다행히 제가 작업하는 테이블을 사용하는 팀은 한 곳 밖에 없었고, 로직을 수정해주셔서 zeroDateTime을 걷어낼 수 있었습니다.

[2]. jdbcTemplate.batchUpdate

jdbcTemplate.batchUpdate를 사용하면 zeroDateTime을 넣을 수 있습니다.

PreparedStatement에서 파라미터를 넣을 수 있는데, timestamps 대신 string을 넣을 수 있습니다.

"0000-00-00 00:00:00"문자열을 넣어서 데이터베이스에 zeroDateTime을 넣을 수 있습니다.

아래 예시 코드 살펴보시면 됩니다.

package com.laboratorykkoon9.kotlinspring.cafe.service

import com.laboratorykkoon9.kotlinspring.cafe.repository.CafeRepository
import com.laboratorykkoon9.kotlinspring.cafe.service.model.CreateCafeDto
import com.laboratorykkoon9.kotlinspring.cafe.service.model.UpdateCafeDto
import mu.KotlinLogging
import org.springframework.data.domain.Pageable
import org.springframework.jdbc.core.BatchPreparedStatementSetter
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.sql.PreparedStatement

@Service
class CafeService(
    private val jdbcTemplate: JdbcTemplate
) {
    val logger = KotlinLogging.logger {}
    private fun batchUpdate(list: List<Long>) {
        try {
            jdbcTemplate.batchUpdate("""
                update menus
                set modified_at=?
                where id=?
            """,
                object : BatchPreparedStatementSetter {
                    override fun setValues(ps: PreparedStatement, i: Int) {
                        ps.setString(1, "0000-00-00 00:00:00")
                        ps.setLong(2, list[i])
                    }

                    override fun getBatchSize(): Int {
                        return list.size
                    }
                }
            )
        } catch (e: Exception) {
            logger.error("fail batch update", e)
        }
    }
}

 

결론

위에서 언급했듯이 zeroDateTime을 사용하기 보다는 다른 방법으로 처리하는걸 고민해보시길 바랍니다.

무조건 사용해야 한다면 convertToNull 옵션과 함께 create 혹은 update를 사용할 때에는 jdbcTemplate.batchUpdate를 사용하는 걸 추천드립니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함