java程序解析jts的geometry类型并入PG数据库

5 篇文章 0 订阅
3 篇文章 0 订阅

场景

GIS开发,会有需要将jts包中的geometry类型数据存入pg(postgis扩展后)数据库的需求。

工程是springboot,mybatis作为持久层框架。

解决方案

1. pg的geometry字段对应的类型为geometry类型,比如:

2. 定义geometry的typeHandler,在mapper.xml中声明使用

背景知识

postgis的geometry字段存储的数据在内部是二进制数据(即PostgreSQL的bytea数据类型),WKB/EWKB也是二进制数据类型。字符集为ascii。

但是通常我们查询数据库时,geometry数据会表示为HEXEWKB数据类型(EWKB对应的十六进制形式)。例如执行以下查询:

SELECT ST_GeomFromEWKT('POINT (1 1)'); 
-- 或者直接从一个有geometry的表里查询出来一个geometry
select geom from i_table limit 1; -- geom就是geometry类型的字段

得到的结果为:

这和执行以下两个查询得到的结果是一样的:

SELECT ST_AsHEXEWKB(ST_GeomFromEWKT('POINT (1 1)')); 
SELECT encode(ST_AsEWKB(ST_GeomFromEWKT('POINT (1 1)')), 'hex'); 

 详情可以查看这篇文章:

PostGIS空间数据类型的组织与表达(一):Geometry - 知乎

所以存储时需要将jts的geometry对象转换为ewkb的二进制格式即可存入pg的geometry字段。

查询时也只需要将二进制转换为geometry即可。

实现

typehandler

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.WKBReader;
import org.locationtech.jts.io.WKBWriter;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class GeometryTypeHandler implements TypeHandler<Geometry> {
    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, Geometry geometry, JdbcType jdbcType) throws SQLException {
        int dimension = geometry.getDimension();
        dimension = (dimension == 2 || dimension == 3) ? dimension : 2;
        WKBWriter wkbWriter = new WKBWriter(dimension, true);
        final byte[] write = wkbWriter.write(geometry);
        preparedStatement.setBytes(i, write);
    }

    @Override
    public Geometry getResult(ResultSet resultSet, String s) throws SQLException {
        final byte[] bytes = resultSet.getBytes(s);
        return bytes2Geometry(bytes);
    }

    @Override
    public Geometry getResult(ResultSet resultSet, int i) throws SQLException {
        final byte[] bytes = resultSet.getBytes(i);
        return bytes2Geometry(bytes);
    }

    @Override
    public Geometry getResult(CallableStatement callableStatement, int i) throws SQLException {
        final byte[] bytes = callableStatement.getBytes(i);
        return bytes2Geometry(bytes);
    }

    private Geometry bytes2Geometry(byte[] bytes) {
        WKBReader wkbReader = new WKBReader();
        try {
            return wkbReader.read(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.jfqqq.vector.mapper.IGeomMapper">
    <resultMap id="resultMap" type="com.jfqqq.vector.entity.MyGeom">
        <result property="gid" column="gid"/>
        <result property="version" column="version"/>
        <result property="geom" column="geom"
                typeHandler="com.jfqqq.vector.typeHandler.GeometryTypeHandler"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

    <sql id="SELECT_BASE_COLUMN">
        gid, version, st_asewkb(geom) as geom, create_time
    </sql>

    <insert id="insert" parameterType="com.jfqqq.vector.entity.MyGeom" useGeneratedKeys="true" keyProperty="gid">
        insert into i_geometry(
            version, geom, create_time
        )
        values (
                   #{version},
                   #{geom,typeHandler=com.jfqqq.vector.typeHandler.GeometryTypeHandler},
                   now()
               )
    </insert>
    <select id="queryByBoxAndVersion"  resultMap="resultMap">
        select <include refid="SELECT_BASE_COLUMN" /> from i_geometry
        where version = #{version} and st_intersects(geom, st_makeenvelope(${bbox.minX}, ${bbox.minY}, ${bbox.maxX}, ${bbox.maxY}, 4326)) = true;
    </select>
</mapper>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL的Geometry类型通常存储在数据库中的二进制格式为WKB(Well-Known Binary)格式。要在Java解析MySQL中的Geometry类型,可以使用JDBC和Java自带的ByteBuffer类来读取WKB格式的二进制数据,然后使用JTS库来解析Geometry类型。以下是解析MySQL中的Geometry类型的示例代码: ```java import java.nio.ByteBuffer; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.WKBReader; public class GeometryParser { private final Connection conn; public GeometryParser(String url, String user, String password) throws SQLException { Properties props = new Properties(); props.setProperty("user", user); props.setProperty("password", password); this.conn = DriverManager.getConnection(url, props); } public Geometry parseGeometry(String tableName, String columnName, int id) throws SQLException { String sql = String.format("SELECT %s FROM %s WHERE id=?", columnName, tableName); try (PreparedStatement stmt = conn.prepareStatement(sql)) { stmt.setInt(1, id); try (ResultSet rs = stmt.executeQuery()) { if (rs.next()) { byte[] wkb = rs.getBytes(1); return parseWkb(wkb); } else { throw new SQLException("No data found"); } } } } private Geometry parseWkb(byte[] wkb) throws SQLException { WKBReader reader = new WKBReader(); ByteBuffer buffer = ByteBuffer.wrap(wkb); // 设置字节顺序为大端模式 buffer.order(ByteOrder.BIG_ENDIAN); try { return reader.read(buffer); } catch (com.vividsolutions.jts.io.ParseException e) { throw new SQLException("Failed to parse geometry", e); } } } ``` 在上面的示例代码中,首先使用JDBC连接到MySQL数据库,然后使用PreparedStatement执行SQL语句,读取指定表格、列名和ID的Geometry数据。接着,使用Java自带的ByteBuffer类读取WKB格式的二进制数据,并使用JTS库提供的WKBReader类解析Geometry类型。最后,返回解析得到的Geometry对象。 在使用上述代码时,需要通过以下步骤来准备开发环境: 1. 下载并添加JTS库的依赖。可以通过Maven等工具来管理依赖,或者手动下载jar包并添加到项目中。 2. 添加MySQL的JDBC驱动依赖。可以通过Maven等工具来管理依赖,或者手动下载jar包并添加到项目中。 3. 确保MySQL数据库中已经创建了包含Geometry类型的表格,并插入了相应的数据。在创建表格时,需要指定Geometry类型的列的数据类型GEOMETRY,并在插入数据时将Geometry类型的数据转换为WKB格式的二进制数据。例如: ```sql CREATE TABLE mytable ( id INT PRIMARY KEY, geom GEOMETRY NOT NULL ); INSERT INTO mytable (id, geom) VALUES (1, ST_GeomFromText('POINT(1 2)')); ``` 通过以上步骤,就可以在Java解析MySQL中的Geometry类型了。需要注意的是,JTS库支持的Geometry类型比MySQL的Geometry类型更加丰富,如果需要解析MySQL中不支持的Geometry类型,可能需要进行额外的转换或处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值