当前位置:   article > 正文

Mybatis-plus使用BaseTypeHandler,完成Pgsql中geometry二进制与坐标点互相转换_mybatisplus typehandler geometry

mybatisplus typehandler geometry

一、通过BaseTypeHandler将数据库中二进制与坐标点转换

你还在使用xml中写st_geomfromewkt(#{geom})进行坐标点导入么?
你还在使用xml中写st_astext(geom)进行二进制查询坐标点?
如果觉得复杂了,请看下放。

首先直接说方法,后面有说明用到的类

1.1 maven导入pgsql驱动与postgis

<!-- Postgresql驱动包 -->
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
</dependency>

<dependency>
    <groupId>net.postgis</groupId>
    <artifactId>postgis-jdbc</artifactId>
    <version>2.5.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

1.2 继承BaseTypeHandler,创建MyGeometryTypeHandler类
因为用到了srid,如果没有用到可以删除,用到了但不是4326,可以自行替换

@MappedTypes({String.class})
public class MyGeometryTypeHandler extends BaseTypeHandler<String> {

    @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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

1.3 实体类添加标签

@Data
@TableName(value = "tland", autoResultMap = true)
public class Tland extends BaseEntity {

    private static final long serialVersionUID = 1L;

    /**
     * 自增id
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 空间坐标
     */
    @TableField(typeHandler = MyGeometryTypeHandler.class)
    private String geom;
    /**
     * 地块编号
     */
    private String landcode;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

核心在于
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"
}
  • 1
  • 2
  • 3
  • 4
  • 5

保存后数据为
在这里插入图片描述

二、说明

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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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);
  • 1
  • 2
  • 3
  • 4

通过新建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;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

二进制转坐标点

PGgeometry pGgeometry = new PGgeometry(string);
if (pGgeometry == null) {
    return null;
}
String s = pGgeometry.toString();
return s.replace("SRID=4326;", "");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

核心与坐标点转二进制一致,就不说明了

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/870376
推荐阅读
相关标签
  

闽ICP备14008679号