超圖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);
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章