You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中MyBatis Map自定义TypeHandler异常排查与修复

问题排查与修复方案

一、解决monthlyCounts字段为null的问题

核心原因及修复动作:

  • 自定义TypeHandler未注册
    确保MyBatis能识别你的TypeHandler:
    • 直接在TypeHandler类上添加注解:
      @MappedTypes(Map.class)
      @MappedJdbcTypes(JdbcType.VARCHAR)
      public class MapStringIntegerTypeHandler extends BaseTypeHandler<Map<String, Integer>> {
          // 实现逻辑
      }
      
    • 或者在Spring Boot配置文件中指定扫描路径:
      mybatis:
        type-handlers-package: com.yourproject.handler
      
  • Mapper XML未关联TypeHandler
    在结果映射中明确指定字段使用自定义处理器:
    <resultMap id="TaskCountResponseMap" type="com.yourproject.dto.TaskCountResponse">
      <result property="monthlyCounts" column="monthly_counts" typeHandler="com.yourproject.handler.MapStringIntegerTypeHandler"/>
    </resultMap>
    
  • SQL未返回目标字段
    检查SQL语句,确保查询结果包含monthly_counts字段(与实体类字段对应)。

二、解决JSON拼接的解析错误问题

错误根源:

手动拼接JSON时容易出现格式不规范,比如循环拼接键值对时多了冗余逗号、字符串未转义等,导致JSON格式无效。

修复方案:

方案1:用数据库内置函数生成标准JSON(推荐)

利用数据库自带的JSON聚合函数,避免手动拼接的格式问题:

  • MySQL:
    SELECT JSON_OBJECTAGG(month, count) AS monthly_counts
    FROM task_stats
    GROUP BY year
    
  • PostgreSQL:
    SELECT json_object_agg(month, count) AS monthly_counts
    FROM task_stats
    GROUP BY year
    

方案2:修正手动拼接逻辑

如果必须手动拼接,严格保证格式规范:
以MySQL为例,用GROUP_CONCAT处理逗号分隔:

SELECT CONCAT('{', GROUP_CONCAT(CONCAT('"', month, '":', count) SEPARATOR ','), '}') AS monthly_counts
FROM task_stats
GROUP BY year

注意:如果month是字符串类型,要确保引号转义正确,避免语法错误。

三、正确的自定义TypeHandler实现示例

确保处理器能完成JSON与Map的双向转换:

@MappedTypes(Map.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class MapStringIntegerTypeHandler extends BaseTypeHandler<Map<String, Integer>> {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Map<String, Integer> parameter, JdbcType jdbcType) throws SQLException {
        try {
            ps.setString(i, OBJECT_MAPPER.writeValueAsString(parameter));
        } catch (JsonProcessingException e) {
            throw new SQLException("Map转JSON字符串失败", e);
        }
    }

    @Override
    public Map<String, Integer> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return parseJson(rs.getString(columnName));
    }

    @Override
    public Map<String, Integer> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return parseJson(rs.getString(columnIndex));
    }

    @Override
    public Map<String, Integer> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return parseJson(cs.getString(columnIndex));
    }

    private Map<String, Integer> parseJson(String json) throws SQLException {
        if (json == null || json.isEmpty()) {
            return Collections.emptyMap();
        }
        try {
            return OBJECT_MAPPER.readValue(json, new TypeReference<Map<String, Integer>>() {});
        } catch (JsonProcessingException e) {
            throw new SQLException("JSON字符串转Map失败", e);
        }
    }
}

内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:13:12