你还在使用xml中写st_geomfromewkt(#{geom})进行坐标点导入么?
你还在使用xml中写st_astext(geom)进行二进制查询坐标点?
如果觉得复杂了,请看下放。
首先直接说方法,后面有说明用到的类
1.1 maven导入pgsql驱动与postgis
org.postgresql postgresql net.postgis postgis-jdbc 2.5.0
1.2 继承BaseTypeHandler,创建MyGeometryTypeHandler类
因为用到了srid,如果没有用到可以删除,用到了但不是4326,可以自行替换
@MappedTypes({String.class})
public class MyGeometryTypeHandler extends BaseTypeHandler {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
PGgeometry pGgeometry = new PGgeometry(parameter);
Geometry geometry = pGgeometry.getGeometry();
geometry.setSrid(4326);
ps.setObject(i, pGgeometry);
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
String string = rs.getString(columnName);
return getResult(string);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String string = rs.getString(columnIndex);
return getResult(string);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String string = cs.getString(columnIndex);
return getResult(string);
}
private String getResult(String string) throws SQLException {
PGgeometry pGgeometry = new PGgeometry(string);
if (pGgeometry == null) {
return null;
}
String s = pGgeometry.toString();
return s.replace("SRID=4326;", "");
}
}
1.3 实体类添加标签
@Data
@TableName(value = "tland", autoResultMap = true)
public class Tland extends BaseEntity {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField(typeHandler = MyGeometryTypeHandler.class)
private String geom;
private String landcode;
}
核心在于
1、@TableField(typeHandler = MyGeometryTypeHandler.class)
通过拦截的方法拦截转换字段
2、@TableName(value = “tland”, autoResultMap = true)
如果不加autoResultMap =rue,
进不去MyGeometryTypeHandler中getNullableResult()这个方法,就会导致无法将二进制转回到坐标点。
1.4 保存与查询数据
通过Mybatis-plus,insert(),或updateById()等方法导入。会将坐标点转换成二进制入库。
通过Mybatis-plus,selectOne()等查询方法,可以将二进制数据转换为坐标点。
保存时请求入参为
{
"id": 75446,
"geom": "POLYGON((77.97868543333607 39.43378804933673,77.978492314287 39.4337826849187,77.97842794127064 39.434056270238216,77.9780417031725 39.43412064325457,77.97858887381153 39.43414746534472,77.97868543333607 39.43378804933673))",
"landcode": "653130204000008069"
}
保存后数据为
2.1 BaseTypeHandler说明
BaseTypeHandler 是个抽象类,需要子类去实现其定义的 4 个抽象方法,而它本身实现了 typeHandler 接口的 4
个方法。可以对数据保存与查询时做出相应处理,类似操作数据库之间的一个拦截器
可以通过该类做密码加密解密操作
上文中坐标点与二进制转换可以看成是一个操作
首先自定义handler 继承BaseTypeHandler重写他里边的四个方法
public abstract void setNonNullParameter(PreparedStatement var1, int var2, T var3, JdbcType var4) throws SQLException; public abstract T getNullableResult(ResultSet var1, String var2) throws SQLException; public abstract T getNullableResult(ResultSet var1, int var2) throws SQLException; public abstract T getNullableResult(CallableStatement var1, int var2) throws SQLException;
setNonNullParameter()
可以理解为加密操作,将带有标签的字段,在inster,update操作时进行拦截,执行实现setNonNullParameter()方法体中的逻辑。
getNullableResult()
可以理解为解密操作,将带有标签的字段,在select操作时进行拦截,执行实现getNullableResult()方法体中的逻辑。
2.1 postgis说明
上文中用到的是postgis-jdbc,这样可以通过工具类,将坐标点与二进制进行转换。
坐标点转二进制
PGgeometry pGgeometry = new PGgeometry(parameter); Geometry geometry = pGgeometry.getGeometry(); geometry.setSrid(4326); ps.setObject(i, pGgeometry);
通过新建PGgeometry对象,传入坐标点或者二进制字符串都可以。具体可以查看PGgeometry的构造函数。点到最下面会发现有这段代码。判断你的入参是什么,就执行什么方法。
public static Geometry geomFromString(String value, BinaryParser bp, boolean haveM)
throws SQLException {
value = value.trim();
int srid = Geometry.UNKNOWN_SRID;
if (value.startsWith(SRIDPREFIX)) {
// break up geometry into srid and wkt
String[] parts = splitSRID(value);
value = parts[1].trim();
srid = Geometry.parseSRID(Integer.parseInt(parts[0].substring(5)));
}
//这里是核心,自己理解逻辑
Geometry result;
if (value.startsWith("00") || value.startsWith("01")) {
result = bp.parse(value);
} else if (value.endsWith("EMPTY")) {
// We have a standard conforming representation for an empty
// geometry which is to be parsed as an empty GeometryCollection.
result = new GeometryCollection();
} else if (value.startsWith("MULTIPOLYGON")) {
result = new MultiPolygon(value, haveM);
} else if (value.startsWith("MULTILINESTRING")) {
result = new MultiLineString(value, haveM);
} else if (value.startsWith("MULTIPOINT")) {
result = new MultiPoint(value, haveM);
} else if (value.startsWith("POLYGON")) {
result = new Polygon(value, haveM);
} else if (value.startsWith("LINESTRING")) {
result = new LineString(value, haveM);
} else if (value.startsWith("POINT")) {
result = new Point(value, haveM);
} else if (value.startsWith("GEOMETRYCOLLECTION")) {
result = new GeometryCollection(value, haveM);
} else {
throw new SQLException("Unknown type: " + value);
}
if (srid != Geometry.UNKNOWN_SRID) {
result.srid = srid;
}
return result;
}
二进制转坐标点
PGgeometry pGgeometry = new PGgeometry(string);
if (pGgeometry == null) {
return null;
}
String s = pGgeometry.toString();
return s.replace("SRID=4326;", "");
核心与坐标点转二进制一致,就不说明了



