#spring-boot #kotlin #h2 #mybatis
#весенняя загрузка #kotlin #h2 #mybatis
Вопрос:
У меня проблема с пользовательским картографом iBatis с H2.
У меня есть текстовый столбец H2 (CLOB), в котором у меня есть строка, и когда я запускаю запрос:
@Select("select issue, count(*) from complaints WHERE company = #{companyName} group by issue order by 2 desc;")
fun getIssueCountsByCompanyName(@Param("companyName") companyName: String): List<Pair<String, Long>>
У меня есть пользовательский TypeMapper, который, как я вижу, работает и правильно извлекает строку из CLOB:
@MappedJdbcTypes(JdbcType.VARCHAR, JdbcType.CLOB, JdbcType.CHAR, JdbcType.NVARCHAR)
@MappedTypes(String::class)
class ClobTypeHandler: TypeHandler<String> {
override fun setParameter(ps: PreparedStatement?, i: Int, parameter: String?, jdbcType: JdbcType?) {
TODO("Not yet implemented")
}
fun getFromCol(col: Any?): String{
if(col == null){ return "" }
if(col is JdbcClob){
val returnValue =StreamUtils.copyToString(col.asciiStream, UTF_8)
// Examining with debugger shows `returnValue` is the correct String here
return returnValue
}
else {
return col.toString()
}
}
override fun getResult(rs: ResultSet?, columnName: String?): String {
return getFromCol(rs?.getObject(columnName))
}
override fun getResult(rs: ResultSet?, columnIndex: Int): String {
return getFromCol(rs?.getObject(columnIndex))
}
override fun getResult(rs: CallableStatement?, columnIndex: Int): String {
return getFromCol(rs?.getObject(columnIndex))
}
}
Вот мой тест:
@Test
fun test_getIssues(){
var issueCounts = complaintMapper.getIssueCounts();
var issueCount = issueCounts.get(0)
assertFalse(issueCount.first.startsWith("clob"))
}
Я получаю эту ошибку:
org.h2.jdbc.JdbcClob не может быть приведен к java.lang.Строка java.lang.ClassCastException: org.h2.jdbc.JdbcClob не может быть приведен к java.lang.Строка
Итак, похоже, что каким-то образом MyBatis вызывает метод, как я ожидаю, и метод возвращает правильное строковое значение, но когда MyBatis помещает данные в возвращаемый объект, он вводит в него неправильное значение (CLOB вместо строки, которую он получил от mapper)
Что здесь происходит? Это агрегация, которая вызывает это, я не понимаю…
Комментарии:
1. Вам действительно нужен пользовательский обработчик типов?
String
Я полагаю, что в большинстве случаев встроенногоStringTypeHandler
достаточно. Предполагая, что вам нужно использовать пользовательский обработчик типов, пожалуйста, предоставьте небольшой исполняемый проект, подобный этому . С вашим объяснениемClassCastException
не имеет смысла, еслиreturnValue
уже есть aString
, поэтому нам лучше иметь repro .2. Итак, StringTypeHandler из MyBatis возвращает данные с «clob 1: ‘Фактическая строка'» — так что да, мне нужен обработчик для H2 — я понял, что если я использую свой общий класс Pair, мне нужно указать обработчик для столбца, который будет моим пользовательским обработчиком, через аннотацию @Result
3. @ave — Я предполагаю, что я имею в виду, что обработчик oob из mybatis не обрабатывает извлечение текстового столбца H2 из результирующего набора и помещение его в общий, который ожидает строку. У меня есть небольшое хранилище с таблицей из 2 столбцов, которая показывает такое поведение — где я должен его опубликовать? Как ошибка в репозитории github?
4. Я рад узнать, что вы нашли решение! Я не уверен, почему встроенный StringTypeHandler не работает для вас. К вашему сведению, самый простой способ поделиться своим проектом — создать новый репозиторий с вашей учетной записью GitHub и загрузить проект туда.
5. На основе mybatis github StringTypeHandler.java класс, это
ResultSet .getString
метод драйвера H2 (при вызове в столбце CLOB), из которого он не считываетсяcol.asciiStream
— похоже, он просто вызываетtoString
метод и получает эту строку
Ответ №1:
Оказывается, это исправляет это:
@Results(Result(column = "first", property = "first", typeHandler = H2ClobTypeHandler::class))
@Select("select issue as first, count(*) as second from complaints WHERE company = #{companyName} group by issue order by 2 desc;")
fun getIssueCountsByCompanyName(@Param("companyName") companyName: String): List<Pair<String, Long>>
Это как-то связано с выбором в общий, который вводится с помощью строки, когда столбец H2 является типом ТЕКСТА.