自定义TypeHandler 将mysql返回的逗号分隔的String转换到List

sql执行如下:

这里我定义的接受类:

但是这里报了错JSON parse error: Cannot deserialize value of type java.util.ArrayList<java.lang.String>from Object value (token JsonToken.START_OBJECT); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type java.util.ArrayList<java.lang.String> from Object value (token JsonToken.START_OBJECT)at [Source: (PushbackInputStream); line: 1, column: 1]",

后来才发现,mysql的GROUP_CONCAT返回的是字符串String类型,无法映射到定义的list里面,MyBatis 返回的结果集与接收结果的对象类型不匹配。

方法一:这里可以修改接受类:,用String接受,在用String的split方法分割处理成List

java 复制代码
    private String pdbId;
    private String uniprotId;
    private String geneSymbol;

方法二:自定义一个 TypeHandler 来处理逗号分隔的字符串到列表的转换:

java 复制代码
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

//自定义一个 TypeHandler 来处理逗号分隔的字符串到列表的转换
public class CommaSeparatedStringTypeHandler extends BaseTypeHandler<List<String>> {

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, List<String> strings, JdbcType jdbcType) throws SQLException {
        if (strings != null) {
            preparedStatement.setString(i, String.join(",", strings));
        } else {
            preparedStatement.setNull(i, jdbcType.TYPE_CODE);
        }
    }

    @Override
    public List<String> getNullableResult(ResultSet resultSet, String s) throws SQLException {
        String result = resultSet.getString(s);
        return convertStringToList(result);
    }

    @Override
    public List<String> getNullableResult(ResultSet resultSet, int i) throws SQLException {
        String result = resultSet.getString(i);
        return convertStringToList(result);
    }

    @Override
    public List<String> getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        String result = callableStatement.getString(i);
        return convertStringToList(result);
    }

    private List<String> convertStringToList(String input) {
        if (input == null || input.isEmpty()) {
            return null;
        }
        return Arrays.asList(input.split(","));
    }
}

在xml文件里自定义结果集映射并指定类型转换器:

java 复制代码
 <resultMap id="pdbMap" type="com.herb.system.api.model.resp.analysis.PdbSearchResponse">
        <id property="pdbId" column="pdbId"/>
        <result property="uniprotId" column="uniprotId" javaType="java.util.List" jdbcType="VARCHAR" typeHandler="com.herb.entity.config.CommaSeparatedStringTypeHandler"/>
        <result property="geneSymbol" column="geneSymbol" javaType="java.util.List" jdbcType="VARCHAR" typeHandler="com.herb.entity.config.CommaSeparatedStringTypeHandler"/>
    </resultMap>

    <select id="getUniportSymbolOfPdb" resultMap="pdbMap">

        SELECT up.pdb_id as pdbId, GROUP_CONCAT(up.uniprot) AS uniprotId , GROUP_CONCAT(ug.gene_symbol) AS geneSymbol
        FROM `uniprot_pdb`  up  LEFT JOIN uniprot_gene ug on up.uniprot =  ug.uniprot
        WHERE up.pdb_id in
        <foreach collection="pdbIdList" item="id"  open="(" close=")" separator=",">
            #{id}
        </foreach>
        GROUP BY up.pdb_id
    </select>

需要注意的是,一般需要在 MyBatis 配置文件中注册这个自定义的 TypeHandler,在 src/main/resources 目录下创建一个 mybatis-config.xml 配置文件文件,在 配置文件中添加如下的配置:

java 复制代码
<configuration>
    <typeHandlers>
        <!-- 注册自定义的 TypeHandler -->
        <typeHandler handler="your.package.path.CommaSeparatedStringTypeHandler"/>
    </typeHandlers>
</configuration>

然后在 application.properties 或 application.yml 文件中添加 MyBatis 的配置mybatis.config-location=classpath:mybatis-config.xml

但是在springboot里面,我没有加入上面的注册,也能运行,原因是MyBatis 可以通过自动扫描的方式发现自定义的 TypeHandler 而无需显式地在 中进行注册。这是因为 MyBatis 会默认扫描某些特定的包路径,例如 org.apache.ibatis.type。如果你的自定义 TypeHandler 的包路径在默认扫描路径下,MyBatis 可能会自动发现并注册它。

运行结果:

相关推荐
小吴编程之路4 小时前
MySQL 索引核心特性深度解析:从底层原理到实操应用
数据库·mysql
~莫子4 小时前
MySQL集群技术
数据库·mysql
凤山老林4 小时前
SpringBoot 使用 H2 文本数据库构建轻量级应用
java·数据库·spring boot·后端
就不掉头发5 小时前
Linux与数据库进阶
数据库
与衫5 小时前
Gudu SQL Omni 技术深度解析
数据库·sql
咖啡の猫5 小时前
Redis桌面客户端
数据库·redis·缓存
oradh5 小时前
Oracle 11g数据库软件和数据库静默安装
数据库·oracle
what丶k5 小时前
如何保证 Redis 与 MySQL 数据一致性?后端必备实践指南
数据库·redis·mysql
_半夏曲5 小时前
PostgreSQL 13、14、15 区别
数据库·postgresql
把你毕设抢过来5 小时前
基于Spring Boot的社区智慧养老监护管理平台(源码+文档)
数据库·spring boot·后端