使用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完全一致:
- 修改
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转换:
- 在Repository类中初始化全局
WKBReader(线程安全,无需每次创建):
private final WKBReader wkbReader = new WKBReader();
- 修改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,正确处理列表类型参数:
- 替换Repository注入的Bean:
private final NamedParameterJdbcTemplate jdbcTemplate;
- 修改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
相关产品推荐
相关产品推荐

