반응형
이번 포스팅에선 ResultType, ResultClass에 Enum을 사용하는 방법에 대해 알아보겠다.
문제
아래와 같이 Customer를 ResultType으로 쓰는 쿼리가 있다.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.spring_kotlin_mybatis.CustomerMapper">
<resultMap id="customerMap" type="com.example.spring_kotlin_mybatis.Customer">
<result property="customerName" column="customer_name"/>
<result property="id" column="id"/>
</resultMap>
<select id="findByIdAndName" resultType="com.example.spring_kotlin_mybatis.Customer">
SELECT customer_name, id
FROM customer
<include refid="findByIdAndNameWhere" />
</select>
<sql id="findByIdAndNameWhere">
<where>
<if test="id != null">
AND id = #{id}
</if>
<if test="name != null">
AND customer_name = #{name}
</if>
</where>
</sql>
</mapper>
Customer 클래스는 아래와 같이 생겼다.
Customer 클래스의 type을 보면 CustomerType이다.
class Customer(
val id: Long,
val customerName: String,
val type: CustomerType
)
enum class CustomerType(
val code: String
) {
GOLD("G"),
BRONZE("B");
}
customer 테이블의 type의 값이 "GOLD", "BRONZE"면 정상적으로 잘 된다.
기본적으로 Enum의 name() 값을 사용해서 잘 된다.
근데 만약 CustomerType에 code값이 DB에 저장되어 있다면?
nested exception is org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'type' from result set. Cause: java.lang.IllegalArgumentException: No enum constant com.example.spring_kotlin_mybatis.CustomerType.B
위와 같은 에러가 발생한다.
해결책
enum에 code로 찾을 수 있는 find method를 추가해주자.
enum class CustomerType(
val code: String
) {
GOLD("G"),
BRONZE("B");
companion object {
fun find(code: String) = CustomerType.values().find { it.code == code }
}
}
이후 type handler를 추가해줘야 한다.
package com.example.spring_kotlin_mybatis.typehandler
import com.example.spring_kotlin_mybatis.CustomerType
import org.apache.ibatis.type.BaseTypeHandler
import org.apache.ibatis.type.JdbcType
import java.sql.CallableStatement
import java.sql.PreparedStatement
import java.sql.ResultSet
class CustomerTypeHandler : BaseTypeHandler<CustomerType>() {
override fun setNonNullParameter(ps: PreparedStatement, i: Int, parameter: CustomerType, jdbcType: JdbcType) {
ps.setString(i, parameter.code)
}
override fun getNullableResult(rs: ResultSet, columnName: String): CustomerType? {
return CustomerType.find(rs.getString(columnName))
}
override fun getNullableResult(rs: ResultSet, columnIndex: Int): CustomerType? {
return CustomerType.find(rs.getString(columnIndex))
}
override fun getNullableResult(cs: CallableStatement, columnIndex: Int): CustomerType? {
return CustomerType.find(cs.getString(columnIndex))
}
}
위 type handler 패키지는 "com.example.spring_kotlin_mybatis.typehandler"다
아래와 같이 설정하자.
// application.yml
mybatis:
type-handlers-package: com.example.spring_kotlin_mybatis.typehandler
// sqlSessionFactory Bean을 별도 설정한 경우
SqlSessionFactoryBean().setTypeHandlersPackage("com.example.spring_kotlin_mybatis.typehandler")
끝!
반응형
'Spring' 카테고리의 다른 글
[Spring] RestTemplate은 정말 Deprecated되는 걸까? 루머 해결 (0) | 2023.07.25 |
---|---|
[Spring] @EnableJpaRepositories bootstrapMode 정리 (0) | 2023.07.09 |
[Spring] Spring Boot + MySQL 설정 방법 (0) | 2023.07.02 |
[Spring] Spring Boot + Kotlin + JPA Native Query 사용법 (2) - entityManager.createNativeQuery (0) | 2023.06.25 |
[Spring] Spring Boot + Kotlin + JPA Native Query 사용법 (1) - @Query (0) | 2023.06.25 |
댓글