1. 程式人生 > >超圖supermap sdx資料庫用sql實現空間查詢

超圖supermap sdx資料庫用sql實現空間查詢

在此介紹用sql對超圖的空間資料庫(sdx)進行空間查詢,優點如下:

1。超圖推薦的方式是用iobject,此方法要引入iobject

2。超圖另一個推薦的方式是用iserver的REST介面,但web介面缺點在於效能一般,尤其是返回資料比較多以及併發頻繁的情況下效能不好

 

超圖空間資料庫支援多種資料庫產品(DBMS),可這種方式只支援PostGIS,也即是下圖的

PS:注意在超圖sdx的體系,Postgresql和PostGIS是兩種資料庫,而開源空間資料庫PostGIS依賴於postgresql,可以說空間資料庫PostGIS也是postgresql,注意區別

PS:超圖idesktop部分版本不支援PostGIS,例如我只在idesktop 9D java 2019(9.1.0)能成功使用

 

當超圖PostGIS資料庫建好後,建立好jdbc連線(本文略,總之按postgresql建連線就行),然後就可以用sql做空間查詢,以及輸出幾何物件

 

sql中使用空間查詢的“介面”跟開源空間資料庫PostGIS是一樣的,原理是超圖PostGIS也相容開源PostGIS的功能

開源PostGIS的空間查詢介面遵循OpenGIS標準,以下是開源PostGIS的官方文件,有介面的詳細說明:https://postgis.net/docs/manual-dev/reference.html

另外個人也可以baidu關鍵詞:postgis查詢,來找到相關文章

 

以下貼一些程式碼

    /**
     * 屬性查詢
     *
     * @throws Exception
     */
    private void attrQuery() throws Exception {
        //屬性查詢
        //例子:查詢名稱為f1的欄位,值等於 面1 的要素(資料/行)

        //圖層名
        //sde資料庫帶空間屬性的表叫圖層,因此圖層跟表類似
        String layerName = "polygon1";

        //獲取預設資料庫連線
        Connection conn = JdbcConnConfigUtil.getDefaultConn();
        //查詢使用的是sql,就是普通的sql
        //select至from之間是輸出的欄位,其中ST_AsText(smgeometry)是輸出幾何物件並轉成wkt格式,smgeometry代表幾何物件,ST_AsText是一個函式可以把幾何物件轉成wkt格式的字串
        //ST_開頭的函式屬於開源空間資料庫PostGIS的功能,可以理解為寫在sql語句裡的一些函式,詳細api在這https://postgis.net/docs/manual-dev/reference.html
        String sql = "select f1,ST_AsText(smgeometry) as wkt" +
                " from " + layerName + " t " +
                //查詢條件,本demo是屬性查詢因此跟一般sql一樣
                "where t.f1='面1'";

        //查詢程式碼,跟jdbc一樣的用法
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            pst = conn.prepareStatement(sql);
            //執行查詢
            rs = pst.executeQuery();
            //while迴圈變數查詢結果
            while (rs.next()) {
                //通過欄位索引獲取欄位值,注意:索引從1開始!!!!
                //獲取幾何物件,wkt格式
                //wkt格式既可以構建幾何物件(如何構建後面有說),也可以輸出到前端供前端使用
                String wkt = rs.getString(2);
                //獲取普通欄位的值
                Long f1 = DataConvertUtil.strToLong(rs.getString(1));
            }
        } finally {
            //關閉連線,清除各種物件
            DbUtils.closeQuietly(conn, pst, rs);
        }
    }
    /**
     * 空間查詢,點查詢面圖層
     *
     * @throws Exception
     */
    private void pointQueryPolygonLayer() throws Exception {
        //空間查詢,點查詢面圖層

        //圖層名
        //sde資料庫帶空間屬性的表叫圖層,因此圖層跟表類似
        String layerName = "polygon1";

        //點以座標形式存在
        double x = 38794.80;
        double y = 25327.295;

        //獲取預設資料庫連線
        Connection conn = JdbcConnConfigUtil.getDefaultConn();
        //獲取圖層的srid
        //srid代表圖層的空間參考(也可以說是座標系),sr=spatial reference
        String srid = SdxUtil.getSridByTableName(conn, layerName, JdbcConnConfigUtil.getDefaultMapProperties());

        conn = JdbcConnConfigUtil.getDefaultConn();
        //查詢使用的是sql,就是普通的sql
        //因為是普通sql,所以在navicat也能執行,除錯sql可以直接在navicat中除錯
        String sql = "select ST_AsText(smgeometry) as wkt" +
                " from " + layerName + " t " +
                //查詢條件,以下寫法意思是查詢面圖層中與點(點座標值就是x,y變數)相交的面
                //其中ST_Intersects是相交的判斷函式,引數是兩個幾何物件,第一個t.smgeometry代表本表的幾何物件
                //第二個ST_PointFromText('POINT(" + x + " " + y + ")', " + srid + "),這裡使用了ST_PointFromText函式通過xy座標值構建點的幾何物件,其中srid是直接使用了圖層的srid

                //關於srid:所以空間物件,例如圖層和幾何物件,都有座標系(也可叫做空間參考),srid就代表座標系
                //在空間查詢,一般來說,被查詢的圖層和作為查詢條件的幾何物件的座標系要統一,否則很可能出錯或造成查詢結果不對

                //ST_Intersects的詳細描述請看api
                "where ST_Intersects(t.smgeometry,ST_PointFromText('POINT(" + x + " " + y + ")', " + srid + ")) = true";

        //查詢程式碼,跟jdbc一樣的用法
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            pst = conn.prepareStatement(sql);
            //執行查詢
            rs = pst.executeQuery();
            //while迴圈變數查詢結果
            while (rs.next()) {
                //通過欄位索引獲取欄位值,注意:索引從1開始!!!!
                //獲取幾何物件,wkt格式
                //wkt格式既可以構建幾何物件(如何構建後面有說),也可以輸出到前端供前端使用
                String wkt = rs.getString(1);
            }
        } finally {
            //關閉連線,清除各種物件
            DbUtils.closeQuietly(conn, pst, rs);
        }
    }
   /**
     * 空間查詢,點緩衝區查詢面圖層
     *
     * @throws Exception
     */
    private void pointBufferQueryPolygonLayer() throws Exception {
        //空間查詢,點緩衝區查詢面圖層

        //圖層名
        //sde資料庫帶空間屬性的表叫圖層,因此圖層跟表類似
        String layerName = "polygon1";

        //點以座標形式存在
        double x = 38821.471;
        double y = 25274.206;
        //緩衝半徑
        double bufferDistance = 100.0;

        //獲取預設資料庫連線
        Connection conn = JdbcConnConfigUtil.getDefaultConn();
        //獲取圖層的srid
        //srid代表圖層的空間參考(也可以說是座標系),sr=spatial reference
        String srid = SdxUtil.getSridByTableName(conn, layerName, JdbcConnConfigUtil.getDefaultMapProperties());

        conn = JdbcConnConfigUtil.getDefaultConn();
        //查詢使用的是sql,就是普通的sql
        String sql = "select ST_AsText(smgeometry) as wkt" +
                " from " + layerName + " t " +
                //查詢條件,以下寫法意思是查詢面圖層中與點的緩衝區相交的面
                //此方法常用於點選地圖查詢點和線,因為點選通常很難絕對點中點和線,所有要加一個小小的緩衝範圍
                //ST_Buffer是構建緩衝區的意思,在此例中是對點物件建立半徑為xx(值在變數bufferDistance)的緩衝區,引數1是幾何物件,引數2是緩衝半徑
                //ST_Buffer外部有select sde.ST_Buffer.... ,大家可能會覺得加這一步多餘(實際上也不會影響查詢結果)
                //ST_Buffer的詳細描述請看api
                "where st_intersects(t.smgeometry,(select ST_Buffer(ST_PointFromText('POINT(" + x + " " + y + ")', " + srid + ")," + bufferDistance + "))) = true";

        //查詢程式碼,跟jdbc一樣的用法
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            pst = conn.prepareStatement(sql);
            //執行查詢
            rs = pst.executeQuery();
            //while迴圈變數查詢結果
            while (rs.next()) {
                //通過欄位索引獲取欄位值,注意:索引從1開始!!!!
                //獲取幾何物件,wkt格式
                //wkt格式既可以構建幾何物件(如何構建後面有說),也可以輸出到前端供前端使用
                String wkt = rs.getString(1);
            }
        } finally {
            //關閉連線,清除各種物件
            DbUtils.closeQuietly(conn, pst, rs);
        }
    }
    /**
     * 空間查詢,線查詢面圖層,也包括使用引數查詢
     *
     * @throws Exception
     */
    private void lineQueryPolygonLayer() throws Exception {
        //空間查詢,線查詢面圖層
        //此demo中查詢條件的線的格式是wkt,因此此demo同樣適用於wkt格式的點線面作為查詢條件

        //圖層名
        //sde資料庫帶空間屬性的表叫圖層,因此圖層跟表類似
        String layerName = "polygon1";

        //作為查詢條件的線,wkt格式
        String queryConditionWkt = "LINESTRING  (38778.80641398 25400.74843392, 38829.229274779995 25320.265790719997, 38787.53344758 25269.35809472)";

        //獲取預設資料庫連線
        Connection conn = JdbcConnConfigUtil.getDefaultConn();
        //獲取圖層的srid
        //srid代表圖層的空間參考(也可以說是座標系),sr=spatial reference
        String srid = SdxUtil.getSridByTableName(conn, layerName, JdbcConnConfigUtil.getDefaultMapProperties());

        conn = JdbcConnConfigUtil.getDefaultConn();
        //查詢使用的是sql,就是普通的sql
        String sql = "select st_astext(t.smgeometry) as wkt,t.f1" +
                " from " + layerName + " t " +
                //查詢條件,以下寫法意思是查詢面圖層中與線(不止線,同樣可用於點和麵)相交的面
                //ST_GeomFromText是傳入的值生成幾何物件,此demo的值是wkt格式,實際不止支援wkt,詳細可看api
                //ST_GeomFromText第一個引數是問號(?)而不是具體的值,問號意思是引數化查詢,把值用引數傳入(如何傳入引數下面有寫),引數查詢是jdbc的特性
                //為何要用引數查詢(而不是直接把值內容拼成string)?因為wkt的長度通常都很長,以本demo為例,一個點的字串長度就有31,假設一條線有1000個點字元長度就是310000,sql語句會超長
                //構建幾何物件的函式還有ST_GeomFromWKB,ST_Polygon,ST_PolygonFromText等等,具體請看api
                " where st_intersects(t.smgeometry,(select ST_GeomFromText(?," + srid + "))) = true" +
                //字元型欄位的引數查詢例子(字元,整形,浮點型的引數化使用都比較簡單,而且類似)
                " and t.f1=?";

        //查詢程式碼,跟jdbc一樣的用法
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            pst = conn.prepareStatement(sql);

            //wkt字元欄位引數查詢例子
            pst.setString(1, queryConditionWkt);

            //字元欄位引數查詢例子
            pst.setString(2, "面2");

            //執行查詢
            rs = pst.executeQuery();
            //while迴圈變數查詢結果
            while (rs.next()) {
                //通過欄位索引獲取欄位值,注意:索引從1開始!!!!
                //獲取幾何物件,wkt格式
                //wkt格式既可以構建幾何物件(如何構建後面有說),也可以輸出到前端供前端使用
                String wkt = rs.getString(1);

                String f1 = rs.getString(2);
            }
        } finally {
            //關閉連線,清除各種物件
            DbUtils.closeQuietly(conn, pst, rs);
        }
    }