Spring JPA - 如何从 PostGis 数据库读取 CIRCULARSTRING?

问题描述 投票:0回答:1

PostGis 数据库中有一个 CircularString (EWKT) 几何图形。它是通过以下 SQL 插入的:

INSERT INTO objectwithgeometries (id,geometry,remarks) VALUES ( 41, ST_SetSRID( ST_GeomFromEWKT( 'CIRCULARSTRING(29.8925 41.36667,29.628611 41.015000,29.27528 41.31667)'), 4326), 'remark-3');

结果是:

尝试 1:尝试使用      postgisRepo.findAll();

读取对象时

...错误是:

org.geolatte.geom.codec.WkbDecodeException:不支持的 WKB 类型代码: 8

在查看 WktDialect 类时,我只看到标准的 7 个 WKB 类型。不是 CurularString。

尝试 2:使用 JDBC 读取:

List<Map<String, Object>> objects = jdbcTemplate.queryForList( String.format( "select id,geometry,remarks from objectwithgeometries where id = %d", id));
objects.forEach( r -> {
        WKBReader wkbReader = new WKBReader();
        PGobject geometryObject = (PGobject) r.get( "geometry");
        byte[] geom = WKBReader.hexToBytes( geometryObject.getValue() );
        try {
            log.info( "Geometry: {}", wkbReader.read(geom));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    });

这也会抛出异常:org.locationtech.jts.io.ParseException: Unknown WKB type 8

Spring Boot 2 或 3(与 Hibernate 5 或 6)没有区别。

Try-3:使用 PGobject、PGGeometry 等。这些对象可通过 maven 依赖项获得:

    <dependency>
        <groupId>net.postgis</groupId>
        <artifactId>postgis-jdbc</artifactId>
        <version>2023.1.0</version>
    </dependency>

这样做的问题是,它在 jdbcTemplate.queryForList() 期间给出错误(未知几何类型:8);-(。

Try-4:通过不同方法的独立示例。效果是一样的:未知几何类型:8。

Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:5433/postgis";
conn = DriverManager.getConnection(url, "xyz", "abc");
((org.postgresql.PGConnection)conn).addDataType("geometry", 
     (Class<? extends PGobject>) Class.forName("net.postgis.jdbc.PGgeometry"));
Statement s = conn.createStatement();
ResultSet r = s.executeQuery("select id,geometry,remarks from objectwithgeometries where id = 43");
while( r.next() ) {
    PGgeometry geom = (PGgeometry)r.getObject(2);
    int id = r.getInt(1);
    System.out.println("Row " + id + ":");
    System.out.println(geom.toString());
}
s.close();
conn.close();

如何在 Spring JPA 中读取这个(EWKT)对象?

我使用 org.hibernate.spatial.dialect.postgis.PostgisDialect 来访问几何图形。

此外,请注意,通过 Spring JPA 执行上述“插入”语句通常会导致连接超时。

spring-data-jpa jts
1个回答
0
投票

终于找到解决办法了。欢迎有更优雅的解决方案。

import org.geotools.geometry.jts.CircularString;
import org.geotools.geometry.jts.CurvedGeometryFactory;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.geometry.jts.WKTReader2;
import org.locationtech.jts.geom.GeometryFactory;
import org.postgresql.util.PGobject;

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class PostgisReaderStandaloneAsText {
    public static void main(String[] args) {
        java.sql.Connection conn;

        try {
            Class.forName("org.postgresql.Driver");
            String url = "jdbc:postgresql://localhost:5433/postgis";
            conn = DriverManager.getConnection(url, "postgis", "postgis");
            Statement s = conn.createStatement();
            ResultSet r = s.executeQuery("select id,ST_AsText(geometry),remarks from objectwithgeometries where id = 43");
            while( r.next() ) {
                String geom = (String) r.getObject(2); 
                int id = r.getInt(1);
                System.out.println("Row " + id + " = " + geom.toString());

                GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
                CurvedGeometryFactory curvedfactory = new CurvedGeometryFactory(Double.MAX_VALUE);

                WKTReader2 reader = new WKTReader2(curvedfactory);
                CircularString arc = (CircularString) reader.read(geom);
                System.out.println( "Arc = " + arc);
            }
            s.close();
            conn.close();
        }
        catch( Exception e ) {
            e.printStackTrace();
        }
    }
}

结果是:

Row 43 = CIRCULARSTRING(29.8925 41.36667,29.628611 41.015,29.27528 41.31667)
Arc = CIRCULARSTRING (29.8925 41.36667, 29.628611 41.015, 29.27528 41.31667)

因为 JTS 无法处理曲线,所以您可以制作一个具有致密(中间 0 个点)的 LineString。

© www.soinside.com 2019 - 2024. All rights reserved.