package org.sxkj.gd.config; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.PrecisionModel; import org.locationtech.jts.io.*; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @MappedTypes({String.class}) @MappedJdbcTypes({JdbcType.OTHER}) public class GeometryTypeHandler extends BaseTypeHandler { @Override public void setNonNullParameter(PreparedStatement preparedStatement, int i, String s, JdbcType jdbcType) throws SQLException { Geometry geo = null; try { // 解析SRID(如果字符串包含SRID=4326;前缀) int srid = 4326; // 默认使用WGS84坐标系 String wktString = s; if (s != null && s.toUpperCase().startsWith("SRID=")) { int semicolonIndex = s.indexOf(';'); if (semicolonIndex > 0) { try { srid = Integer.parseInt(s.substring(5, semicolonIndex)); wktString = s.substring(semicolonIndex + 1); } catch (NumberFormatException e) { // 如果解析失败,使用默认SRID 4326 } } } // 清理WKT字符串:移除多余空格,标准化格式 // 将 "POLYGON ((" 转换为 "POLYGON((" wktString = wktString.replaceAll("\\(\\s+\\(", "((").trim(); // String转Geometry geo = new WKTReader(new GeometryFactory(new PrecisionModel())).read(wktString); // 设置Geometry的SRID geo.setSRID(srid); // Geometry转WKB byte[] geometryBytes = new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN, true).write(geo); preparedStatement.setBytes(i, geometryBytes); } catch (ParseException e) { throw new SQLException("Failed to parse geometry WKT: " + s, e); } } @Override public String getNullableResult(ResultSet resultSet, String s) { try (InputStream inputStream = resultSet.getBinaryStream(s)) { Geometry geo = getGeometryFromInputStream(inputStream); if (geo != null) { return geo.toString(); } } catch (Exception e) { } return null; } @Override public String getNullableResult(ResultSet resultSet, int i) { try (InputStream inputStream = resultSet.getBinaryStream(i)) { Geometry geo = getGeometryFromInputStream(inputStream); if (geo != null) { return geo.toString(); } } catch (Exception e) { } return null; } @Override public String getNullableResult(CallableStatement callableStatement, int i) throws SQLException { return ""; } /** * 流 转 geometry */ private Geometry getGeometryFromInputStream(InputStream inputStream) throws Exception { Geometry dbGeometry = null; if (inputStream != null) { // 二进制流转成字节数组 byte[] buffer = new byte[255]; int bytesRead = 0; ByteArrayOutputStream baos = new ByteArrayOutputStream(); while ((bytesRead = inputStream.read(buffer)) != -1) { baos.write(buffer, 0, bytesRead); } // 得到字节数组 byte[] geometryAsBytes = baos.toByteArray(); // 字节数组小于5 异常 if (geometryAsBytes.length < 5) { } // 字节数组前4个字节表示srid 去掉 byte[] sridBytes = new byte[4]; System.arraycopy(geometryAsBytes, 0, sridBytes, 0, 4); boolean bigEndian = (geometryAsBytes[4] == 0x00); // 解析srid int srid = 0; if (bigEndian) { for (int i = 0; i < sridBytes.length; i++) { srid = (srid << 8) + (sridBytes[i] & 0xff); } } else { for (int i = 0; i < sridBytes.length; i++) { srid += (sridBytes[i] & 0xff) << (8 * i); } } WKBReader wkbReader = new WKBReader(); // WKBReader 把字节数组转成geometry对象。 byte[] wkb = new byte[geometryAsBytes.length - 4]; System.arraycopy(geometryAsBytes, 4, wkb, 0, wkb.length); dbGeometry = wkbReader.read(wkb); dbGeometry.setSRID(srid); } return dbGeometry; } }