티끌모아 로키산맥 🏔
search
로ᄏl
배움에 끝은 없다... 개발 또한 그러하다.
Today
Yesterday
스프링부트 버전업 이슈 LocalTime 값을 DB에서 조회시 Invalid value for NanoOfSecond 오류 분석
스프링부트 버전업 이후 LocalTime 필드를 가지는 Entity를 조회할 때, 아래와 같이 LocalTime의 nano second에 음수 값이 할당되어 에러가 발생했음.
PostgreSQL DB에 저장된 TIME 타입 컬럼을 java의 LocalTime 변환 시에 아래와 같은 오류 발생
java.time.DateTimeException: Invalid value for NanoOfSecond (valid values 0 - 999999999): -843000000
LocalTime 변환 시, 나노초 값으로 음수가 유입되면서 발생
변경된 스프링부트 버전업에 대응되는 하이버네이트 버전에서 변경이 있었고 이 부분에 버그가 존재했음.
하이버네이트 버전이 변경되면서 DB에 LocalTime 저장 로직이 변경됨.
DB에서 시간값을 조회한 후 Time을 LocalTime으로 변환할 때 버그가 존재함
LocalTime 타입을 DB에 저장할 때는 TimeJdbcType.getBinder 메서드를 호출하게된다. 이 내부에서 TemporalJavaType.unwrap 메서드를 호출하여 Time 객체로 변환한다. … ➡️ TimeJdbcType.doBind ➡️ LocalTimeJavaType.unwrap ➡️ new Time(time.getTime() + DateTimeUtils.roundToPrecision( value.getNano(), 3 ) / 1000000)
HikariProxyPreparedStatement.setTime ➡️ PreparedStatementSpy.setTime(index, time)
DB에 저장할 떄는 RdbmsSpecifics.formatParameterObject 메서드를 호출하여 (DML 쿼리를 위한) 문자열로 변경하여 new SimpleDateFormat(dateFormat).format(object) 를 호출하여 MM/dd/yyyy HH:mm:ss.SSS 문자열 포맷으로 파싱하여 저장한다. 이때 object로 들어가는 값은 LocalTimeJavaType.unwrap으로 생성한 Time 이다.
실제로 저장하려고했던 LocalTime은 08:32:00.943476 으로 ms 까지 잘 변환된 것으로 보인다. (4번째 자리 반올림)
DB에 저장된 데이터를 읽어오는 경우
TimeJdbcType.doExtract ➡️ LocalTimeJavaType.wrap 호출하여 LocalTime 으로 변환하게 된다.
Time 객체는 unwrap했을 때(Application → DB)와 동일한 값의 Time 객체를 생성했다. 하지만 ms를 구하는 로직에서 문제가있어 음수의 값이 도출되게 된다.
LocalTime은 날짜 정보(년,월,일)를 가지지 않지만 Time 계산을 위해서는 날짜 정보가 필요하다. 따라서 default 날짜(epochTime or 유닉스 시간(Unix time)인 1970년 1월 1일 00:00:00 UTC에서 년원일)을 임의로 지정해준다. 여기에서 KST 타임존인 경우에는 UTC의 기준을 맞추기 위해서 9시간을 빼주게되고 이때, epochTime은 음수가 나오게된다. (위에서 언급한 유닉스 시간의 경우 0) LocalTime을 Time으로 변환하여 DB에 저장할 때는 문제가 없지만 Time을 LocalTime으로 변환하는 과정에서는 0 ~ UTC와 KST의 시간차이 - 1 시간인 경우에는 fastTime(Time 객체의 상태값) 이 음수가되는데 ms를 이 값에서 1000을 나눈 나머지로 계산하기 때문에 음수 ms가 발생하게된다.
참고로 해당 버그 fix된 것으로 보이지만 아직 release가 안된 상태이다.
LocalTime 객체를 저장하거나 조회할 때는 nano seconds를 제거(or 0으로 초기화)하는 Converter를 구현하여 설정해주어서 저장 혹은 조회 시, nano second가 저장되지 않도록 임시 방편을 취했고 추후 버그 fix 버전으로 release되면 hibernate 버전 업을 진행하려고한다.
Springboot 3 환경에서 Feign Client 에러 (0) | 2023.08.28 |
---|---|
[Github Action] failed to compute cache key: failed to calculate checksum of ref ... 에러 발생 (0) | 2023.08.13 |
gradle 환경에서 Spring REST Docs 문서가 서버에 띄어지지 않는 경우 (0) | 2020.12.26 |
Typo in static class property declaration react/no-typos 오류 해결법 (2) | 2020.07.17 |
java.lang.Exception: No runnable method 오류 해결법 (0) | 2020.03.21 |