#使用GIS数据类型

YashanDB中的ST_GEOMETRY类型是数据库内置的一种自定义类型,用于存储和访问符合开放地理空间信息联盟(Open Geospatial Consortium,简称OGC)制定的SFA SQL标准的几何对象。

ST_GEOMETRY实际上是一种内置的UDT Object类型,具备如下属性:

属性名称 类型 长度
HEAD RAW 40字节
GEOM BLOB < 4G

# 将WKT数据插入ST_GEOMETRY列

如需将WKT数据插入ST_GEOMETRY列中,可以使用ST_GEOMFROMTEXT函数把WKT格式的字符串转成ST_GEOMETRY类型的数据。

示例如下:

        try(Connection connection = Util.getYasConnection()) {
            // 表结构为:create table table1(id int,position  ST_GEOMETRY);
            PreparedStatement preparedStatement = connection.prepareStatement("insert into table1 values (?,ST_GEOMFROMTEXT(?))");
            //各种类型的WKT数据
            String[] values = {"POINT(0 0)",
                    "LINESTRING (1 2,4 5)",
                    "POLYGON ((1 0,1 1,2 2,1 0),(0 0,6 6,8 8,0 0))",
                    "MULTIPOINT ((1 1),(2 2))",
                    "MULTILINESTRING ((1 2,4 5),(2 3,5 6))",
                    "MULTIPOLYGON (((1 5, 4 3, 6 6, 2 6, 1 5)), ((6 5, 8 8, 6 9, 6 5)))",
                    "GEOMETRYCOLLECTION (POINT (1 0),LINESTRING (1 2,4 5))"};
            for (int i = 0; i < values.length; i++) {
                preparedStatement.setInt(1,i);
                preparedStatement.setString(2,values[i]);
                preparedStatement.addBatch();
            }
            preparedStatement.executeBatch();

        }

# 将WKB数据插入ST_GEOMETRY列

如需将WKB数据要插入ST_GEOMETRY列中,可以使用ST_GEOMFROMWKB函数把WKB数据转成ST_GEOMETRY类型的数据,WKB数据通常是BLOB类型或byte[]类型。

示例如下:

        try(Connection connection = Util.getYasConnection()) {
            PreparedStatement preparedStatement = connection.prepareStatement("insert into table1 values (?,ST_GEOMFROMWKB(?))");
            byte[] bytes1 = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            byte[] bytes2 = {1, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, -16, 63, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 16, 64, 0, 0, 0, 0, 0, 0, 20, 64};
            Blob blob = connection.createBlob();
            blob.setBytes(1,bytes2);

            preparedStatement.setInt(1,1);
            preparedStatement.setBytes(2,bytes1);
            preparedStatement.addBatch();

            preparedStatement.setInt(1,2);
            preparedStatement.setBlob(2,blob);
            preparedStatement.addBatch();

            preparedStatement.executeBatch();

        }

# 查询ST_GEOMETRY各种形式的数据

如需查询ST_GEOMETRY各种形式的数据,可以使用ST_ASTEXT、ST_ASBINARY、ST_ASEWKB以及ST_ASGEOJSON等函数分别查询WKT形式、WKB形式、EWKB形式和JSON形式的数据,也可以直接查ST_GEOMETRY列获取完整的Struct类型的数据,然后从Struct中分别取得HEAD数据和BLOB类型的数据,再从BLOB中获取WKB形式的数据。

示例如下:

         try(Connection connection = Util.getYasConnection()) {
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery("select id, ST_ASTEXT(position) , ST_ASBINARY(position), ST_ASEWKB"
                    + "(position), ST_ASGEOJSON(position),position from table1");
            while (rs.next()) {
                String wkt = rs.getString(2);
                System.out.println(wkt); // POINT (0.000000000000000 0.000000000000000)
                byte[] wtb = rs.getBytes(3);
                System.out.println(Arrays.toString(wtb)); // [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
                byte[] ewtb = rs.getBytes(4);
                System.out.println(Arrays.toString(ewtb)); // [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
                String geoJson = rs.getString(5);
                System.out.println(geoJson); // {"type":"Point","coordinates":[0.0,0.0]}
                Struct geometryObject = (Struct) rs.getObject(6);
                Object[] values = geometryObject.getAttributes();
                byte[] head = (byte[]) values[0];
                System.out.println(Arrays.toString(head)); // [0, 1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
                Blob blob = (Blob) values[1];
                byte[] wtbFromBlob = blob.getBytes(1,(int)blob.length());
                System.out.println(Arrays.toString(wtbFromBlob)); // [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
            }
        }

# 插入UDT Object类型的ST_GEOMETRY数据

除了上面提到的使用数据库函数的方式插入WKT或者WKB形式的ST_GEOMETRY数据外,基于其本质上是一个UDT Object类型,还可以使用Struct类型进行参数绑定。只需获取到HEAD和WKB数据即可组装出Struct对象,然后通过参数绑定进行数据插入。但在插入前通常无法获取HEAD信息,因此如需使用参数绑定的方式插入ST_GEOMETRY数据,只能插入从数据库里查出的数据。

示例如下:

        try(Connection connection = Util.getYasConnection()) {
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery("select id,position from table1");
            rs.next();
            Struct geometryObject = (Struct) rs.getObject(2);
            
            PreparedStatement preparedStatement = connection.prepareStatement("insert into table1 values (?,?)");
            
            preparedStatement.setInt(1,3);
            preparedStatement.setObject(2,geometryObject); // 直接把查出来的Struct绑定进去进行插入
            preparedStatement.addBatch();

            // 根据查询所得Struct的Attributes创建新的Struct,再进行参数绑定插入数据
            Struct geometryObject2 = connection.createStruct("MDSYS.ST_GEOMETRY",geometryObject.getAttributes());
            preparedStatement.setInt(1,4);
            preparedStatement.setObject(2,geometryObject2); 
            preparedStatement.addBatch();
            preparedStatement.executeBatch();

            // 根据查询所得Struct的Attributes取出HEAD和BLOB类型的GEOM数据,再从GEOM中取出WKB数据重新构造。使用HEAD与新构造的BLOB一起组装出新的Aattributes来创建Struct,再进行参数绑定插入数据
            Blob geom = (Blob) geometryObject.getAttributes()[1];
            byte[] wtbFromBlob = geom.getBytes(1,(int)geom.length());
            Blob blob1 = connection.createBlob();
            blob1.setBytes(1,wtbFromBlob);
            Object[] attributes = new Object[2];
            attributes[0] = geometryObject.getAttributes()[0]; // head信息
            attributes[1] = blob1;
            Struct geometryObject3 = connection.createStruct("MDSYS.ST_GEOMETRY",attributes);
            preparedStatement.setInt(1,5);
            preparedStatement.setObject(2,geometryObject3);
            preparedStatement.addBatch();
            
            preparedStatement.executeBatch();

        }