Мой пользовательский обработчик типов Batis не работает должным образом

#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 уже есть a String , поэтому нам лучше иметь 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 является типом ТЕКСТА.