从Java的Polygon对象更新几何图形的PostGIS操作

4

我正试图使用外部文件中的数据更新PostGIS几何列。一些多边形中的点数超过35k,ST_GeomFromText方法不适用于文本字符串过长的情况。我可以将点读入一个多边形对象,并想执行以下操作:

PreparedStatement ps = conn.preparedStatment("update x set y = ? where z = ?");
ps.setBinary(1, polygon);
ps.setString(2, key);
ps.executeUpdate();

我找不到任何关于如何做这个的例子。能否有人指向文档或给出一个我可以跟随的示例?

谢谢

2个回答

8

所以,我进行了一些测试,并为您提供了以下示例。我也将其作为Github上的GIST提供,随意克隆和探索。

首先,这是我在一个新数据库gis_data中创建的表的DDL,该数据库是基于template_postgis数据库模板构建的:

CREATE TABLE sample_table
(
  "key" character varying(20) NOT NULL,
  large_poly geometry NOT NULL,
  CONSTRAINT simple_pl PRIMARY KEY (key)
)

下面是我Java示例中使用的表格,请确保使用您的凭据修改DriverManager.getConnection()行。

import java.sql.*;
import java.util.*;
import java.lang.*;
import org.postgis.*;

public class JavaGIS {

    public static void main(String[] args) {
        java.sql.Connection conn;
        try {
            Class.forName("org.postgresql.Driver");
            String url = "jdbc:postgresql://localhost:5432/gis_data";
            conn = DriverManager.getConnection(url, "postgres", "");

            ((org.postgresql.PGConnection)conn).addDataType("geometry",Class.forName("org.postgis.PGgeometry"));
            ((org.postgresql.PGConnection)conn).addDataType("box3d",Class.forName("org.postgis.PGbox3d"));

            Polygon geo = new Polygon(
                            new LinearRing[] {
                                new LinearRing(
                                    new Point[] {
                                        new Point(-1.0d, -1.0d,  0.5d),
                                        new Point( 1.0d, -1.0d,  0.0d),
                                        new Point( 1.0d,  1.0d, -0.5d),
                                        new Point(-1.0d,  1.0d,  0.0d),
                                        new Point(-1.0d, -1.0d,  0.5d)
                                    }
                                )
                            }
                        );
            PreparedStatement s = conn.prepareStatement("INSERT INTO sample_table (key_value, large_poly) VALUES (?, ?)");
            s.setString(1, "poly1");
            s.setObject(2, new PGgeometry(geo));

            int rows = s.executeUpdate();

            if (rows > 0) {
                System.out.println(" Successful insert! ");
            } else {
                System.out.println(" Failed insert!");
            }
            s.close();

            Statement qs = conn.createStatement();
            ResultSet r = qs.executeQuery("SELECT key_value, large_poly FROM sample_table");
            while( r.next() ) {
                /*
                * Retrieve the geometry as an object then cast it to the geometry type.
                * Print things out.
                */
                String key = r.getString(1);
                PGgeometry geom = (PGgeometry)r.getObject(2);

                if (geom.getGeoType() == Geometry.POLYGON) {
                    System.out.println("Found a polygon with key " + key);
                } else {
                    System.out.println("Found a PostGIS geometry object " + geom.getGeoType() + " having key " + key);
                }
            }
            qs.close();
            conn.close();
        }
        catch( Exception e ) {
            e.printStackTrace();
        }
    }
}

请在编译和执行此示例时,确保在类路径中包含最新的Postgresql jdbc驱动程序jarPostGIS jar文件
此示例主要基于PostGIS示例,该示例演示了如何优美简单地选择。由于PostGIS在其扩展方面做得非常出色,因此插入同样很容易。
如果您已经将数据存储在PostGIS Geometry对象中,只需像我的示例一样将其包装在PGgeometry对象中即可将其插入数据库。这将使数据库驱动程序处理如何精确传输它(可能作为二进制数据)。一旦我实际遵循了构建多边形的说明,一切都非常顺利。
免责声明:我只尝试过简单的多边形,但原理是正确的。如果你正在处理非常大的多边形,请告诉我进展如何!

1
那个有效。感谢您抽出时间来准备这个。 - user3361199
1
顺便提一下,我收到了错误信息“索引行大小4096超过了索引的最大2712”,因此不得不删除该索引。我不确定是否可以进行配置。如果不能,那么2712就是多边形需要进行相关选择的最大大小。 - user3361199
很高兴它有帮助!关于你的侧记 - 你是指在几何数据库字段上有一个索引吗?我对限制并不感到惊讶,但值得调查一下PostGIS文档,看看是否有关于如何避免这种限制的提示。无论如何,祝你好运,并感谢你的跟进。 - ProgrammerDan
我创建了错误的空间索引。阅读文档后,我在索引创建中添加了“使用GIST(列名)”,问题得到解决。再次感谢。 - user3361199
完美。享受PostGIS的乐趣吧。我有美好的回忆,期待再次与它合作。 - ProgrammerDan

1

干得好。

但我需要指定SRID(4326),否则数据库将拒绝多边形。

有什么提示吗?

使用字符串解决了它。

String bbox ="SRID=4326;POLYGON(("+lu+","+lo+","+ro+","+ru+","+lu+"))";
pstmt.setObject(12,new PGgeometry(bbox));

1
要通过编程方式设置SRID,首先创建几何对象本身,设置其SRID,然后将其包装在PGgeometry中。例如:org.postgis.Polygon poly = new Polygon(/*...init code...*/); poly.setSrid(4326); PGgeometry geom = new PGgeometry(poly); - avivr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接