Spring JDBC와 JdbcOperations
Spring Data JDBC를 사용할 때, CrudRepository와 자동생성 쿼리 만으로는 커버가 되지 않는 경우가 반드시 생기고, 이 경우 @Query 보다는 JdbcOperations를 쓰는 것이 낫다. (see [Spring Data JDBC] docs)
따라서 CrudRepository를 아래와 같이 Dao로 확장해서 관리하는 것이 좋다.
interface MerchantInfoRepository : NfcJdbcRepository<MerchantInfo, MerchantInfo.CompositeKey>
@Repository
class MerchantInfoDao(
private val merchantInfoRepository: MerchantInfoRepository,
private val jdbcOperations: NamedParameterJdbcOperations
): MerchantInfoRepository by merchantInfoRepository { // delegate 처리해서 interface 노출
fun upsert(merchantInfo: MerchantInfo): Int {
return jdbcOperations.update(
upsertQuery,
ObjectSqlParameterSource(merchantInfo)
)
}
private val upsertQuery = """
MERGE INTO mrc
USING DUAL
ON (mrc_no = :merchantNo...) // bind는 반드시 $가 아니라 :로. (prepared statement)
..."""
}
:param bind
다음 3가지 방법 사용 할 수 있다.
1.
BeanPropertySqlParameterSource(obj)
2.
MapSqlParameterSource()
.addValue("param1", param1)
3.
mapOf("param1" to param1)
여기서 LocalDateTime 같은 타입에 대한 Converter를 자동으로 적용하려면, 아래 2가지 방법 사용 할 수 있다.
1.
objectMapper.converValue(map으로 변환)
objectMapper에 Converter가 등록되어 있어야 한다. (보통은 Auto-config)
이 방법도 나쁘지 않다.
2.
ObjectSqlParameterSource를 직접 정의하고 override해서 Convert 처리
class ObjectSqlParameterSource(
val obj: Any
): BeanPropertySqlParameterSource(obj) {
override fun getValue(paramName: String): Any? {
return when (val value = super.getValue(paramName)) {
is LocalDateTime -> LocalDateTimeToStringConverter.convert(value)
is CustomLocalDate -> CustomLocalDateToStringConverter.convert(value)
is CardNumber -> CardNumberToStringConverter.convert(value)
is CurrencyCode -> CurrencyCodeToStringConverter.convert(value)
else -> value
}
}
/**
* BeanPropertySqlParameterSource.getSqlType을 보면
* JavaType이 Date이면 SqlType을 Timestamp로 만들어버린다.
* 따라서 반드시 override 필요함.
*/
override fun getSqlType(paramName: String): Int {
val sqlType = super.getSqlType(paramName)
return if (sqlType == Types.TIMESTAMP) {
Types.VARCHAR
} else {
sqlType
}
}
}
참고
spring-jdbc-tips/spring-jdbc-core.md at master · benelog/spring-jdbc-tips
'Java Stack > Persistence' 카테고리의 다른 글
[MyBatis] 객체 안의 객체 매핑하기 (ResultMap과 DTO) (0) | 2022.03.12 |
---|---|
[MyBatis] Cache (0) | 2022.03.08 |
redis - java persistence (0) | 2020.03.10 |
[Spring] DB 관련 : Mybatis (3) | 2020.03.04 |