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

使用JdbcTemplate读取MySQL Point类型数据出现转换错误如何解决?

解决方案

问题根因

你配置的MySQL8SpatialDialect是Hibernate Spatial的方言,仅对JPA/Hibernate生效,原生JdbcTemplate属于JDBC浅层封装,没有内置JTS几何类型的转换逻辑,因此无法直接将MySQL返回的Point类型映射为org.locationtech.jts.geom.Point。

可用方案(无需修改SQL调用ST_AsWKT)

方案1:复用Hibernate Spatial现成转换器(推荐)

你已经引入了hibernate-spatial依赖,直接复用内置的MySQL几何类型转换器即可,不需要自己实现解析逻辑,转换效果和JPA完全一致:

  1. 修改NtpJdbcRepository代码,替换报错的坐标赋值逻辑:
import org.hibernate.spatial.dialect.mysql.MySQLGeometryTypeDescriptor;

// 类内其他代码不变
(rs, rowNum) -> {
    // 其他字段赋值保持不变
    Object rawGeom = rs.getObject("coordinates");
    if (rawGeom != null) {
        Point point = (Point) MySQLGeometryTypeDescriptor.INSTANCE.wrap(rawGeom, null);
        ntpSource.setCoordinates(point);
    }
    return ntpSource;
}

该方案不需要额外处理SRID、字节解析等逻辑,和JPA的转换规则完全对齐。

方案2:直接解析WKB二进制数据

如果不想依赖Hibernate的转换逻辑,可以直接读取MySQL返回的WKB二进制数据,用JTS自带的WKBReader转换:

  1. 在Repository类中初始化全局WKBReader(线程安全,无需每次创建):
private final WKBReader wkbReader = new WKBReader();
  1. 修改RowMapper中的坐标赋值逻辑:
(rs, rowNum) -> {
    // 其他字段赋值保持不变
    byte[] wkb = rs.getBytes("coordinates");
    if (wkb != null) {
        try {
            Point point = (Point) wkbReader.read(wkb);
            point.setSRID(4326); // 匹配你字段的SRID配置
            ntpSource.setCoordinates(point);
        } catch (ParseException e) {
            throw new RuntimeException("坐标解析失败", e);
        }
    }
    return ntpSource;
}

额外问题修复

你当前的IN参数写法存在逻辑错误:将id列表拼接为字符串传入单个?,最终SQL执行时会变成IN ('1,2,3'),只能匹配到第一个id值。建议将JdbcTemplate替换为NamedParameterJdbcTemplate,正确处理列表类型参数:

  1. 替换Repository注入的Bean:
private final NamedParameterJdbcTemplate jdbcTemplate;
  1. 修改SQL和参数绑定逻辑:
String selectQuery = "SELECT "
        + "u.idTable,"
        + "u.ntp_id,"
        + "u.dataDT,"
        + "u.ip,"
        + "u.country,"
        + "u.iso_code,"
        + "u.city,"
        + "u.coordinates,"
        + "SUM(u.counts_requests) as counts_requests "
        + "FROM ntp_source AS u "
        + "WHERE u.ntp_id IN (:ntpIds) and u.dataDT BETWEEN :startDate AND :endDate "
        + "GROUP BY u.ip";

MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("ntpIds", ntp_id);
params.addValue("startDate", startDate);
params.addValue("endDate", endDate);

return jdbcTemplate.query(selectQuery, params, (rs, rowNum) -> {
    // 字段赋值逻辑和上述方案一致
});

无效配置说明

你在application.properties中添加的org.springframework.data.jdbc.repository.config.DialectResolver$JdbcDialectProvider配置仅对Spring Data JDBC生效,对原生JdbcTemplate无效,可以直接删除。

内容的提问来源于stack exchange,提问作者devalurum

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 02:06:03