본문 바로가기

Spring

JpaSystemException: Could not extract column [6] from JDBC ResultSet [MONTH] 오류 해결

기존 프로젝트에 기능 추가를 하는 중, 개발 환경에서 db 스키마 변경이 필요했다. 문제는 스키마 변경 후 데이터베이스 정합성, 도메인 무결성 등을 위배하는 데이터들 때문에 기존에 정상적으로 작동하던 API 중 몇몇 API에서 오류가 났다. 그중에 한 API 오류 해결 사례를 정리하는 포스팅.

 

 

에러 발생

{
"code": 400,
"message": "Bad Request / Could not extract column [3] from JDBC ResultSet [MONTH] [n/a] / org.hibernate.exception.GenericJDBCException: Could not extract column [3] from JDBC ResultSet [MONTH] [n/a] / class org.springframework.orm.jpa.JpaSystemException",
"timestamp": "2025-02-18T11:29:36.532228600",
"path": "/v1/user",
"method": "GET"
}

 

유저 목록을 반환하는 API 호출 시 400 에러가 발생했다. 에러 메시지 등으로 파악한 원인은 birthdate 필드의 일부 값이 2000-00-00, 0000-00-00과 같은 잘못된 형식으로 저장되어 있었는데 이 값이 LocalDate 타입으로 변환하려 할 때 오류가 발생하는 것이었다. LocalDate는 YYYY-MM-DD 형식이어야 하며, Month나 Day에 00이 포함된 날짜는 유효하지 않은 값으로 처리된다.

 

data class UserModel(
    val id: Long,
    val email: String,
    val birthDate: LocalDate?,
    )

조회에 사용되는 data 클래스는 위와 같다.

            Projections.constructor(
            UserModel::class.java,
            cgsUserEntity.id,
            cgsUserEntity.email,
            cgsUserEntity.birthdate,
            )

querydsl로 작성된 select 절의 파라미터는 위와 같다.


해결 방법

  • AttributeConverter를 추가하여 해결하였다.
@Converter(autoApply = false)
class LocalDateConverter : AttributeConverter<LocalDate?, String?> {
    override fun convertToDatabaseColumn(attribute: LocalDate?): String? {
        return attribute?.toString()
    }

    override fun convertToEntityAttribute(dbData: String?): LocalDate? {
        return if (dbData == "0000-00-00" || dbData == "2000-00-00") {
            null
        } else {
            dbData?.let { LocalDate.parse(it) }
        }
    }
}

  • 2000-00-00, 0000-00-00과 같은 잘못된 날짜 값을 처리하는 로직을 추가하여, 해당 값을 null로 변환하였다. 프로젝트에서 birthDate를 null 허용 가능 타입을 사용하고 있었으므로 유효하지 않은 값을 그냥 null로 변환하기로 하였다.
  • 엔티티에는 다음과 같이 생성한 컨버터를 명시해 주었다.
    @NotNull
    @Convert(converter = LocalDateConverter::class) // db 0000-00-00 값 등 대응 위해 설정
    @Column(name = "birthdate", nullable = false)
    var birthdate: LocalDate? = null

 

적용 후 API 정상 작동됨을 확인하였다.


내 생각

개발 환경에서도 데이터베이스 정합성과 도메인 무결성은 반드시 지켜야 한다. 아무리 개발 환경에서 사용하는 db라고 무지성으로 부적합한 데이터를 넣는 것은 지양해야 한다. 잘못된 데이터가 들어가면 시스템이 정상적으로 작동하지 않거나, 비즈니스 로직을 깨뜨릴 수 있다. 위 내용은 사실 유효한 데이터만 데이터베이스에 저장되어 있었다면, 굳이 하지 않아도 될 대응이었다.