Oracle Spatial Java API 簡(jiǎn)介

本文簡(jiǎn)要介紹如何使用 Spring JDBC 進(jìn)行基本的空間查詢。

數(shù)據(jù)的準(zhǔn)備

??將空間數(shù)據(jù)存入 Oracle Spatial 的方法有很多種,最基本的一種方法就是直接用 SQL 語句插入數(shù)據(jù),但這種方法效率太低,而且極易出錯(cuò)。我個(gè)人較為喜歡也最常使用的一種方法是借助現(xiàn)成的 GIS 軟件導(dǎo)入數(shù)據(jù)。下面簡(jiǎn)要介紹如何使用 ArcCatalog 將矢量數(shù)據(jù)導(dǎo)入 Oracle Spatial。

連接數(shù)據(jù)庫

  1. 在 ArcCatalog 的目錄樹中,找到數(shù)據(jù)庫連接,展開后有一個(gè)添加數(shù)據(jù)庫連接,雙擊之后就會(huì)打開如下的窗口:


    數(shù)據(jù)庫連接窗口
  2. 按照?qǐng)D中的示范填寫相關(guān)屬性,實(shí)例這一項(xiàng)的格式是 主機(jī):端口/數(shù)據(jù)庫實(shí)例名。點(diǎn)擊確定,然后就會(huì)連接到 Oracle。注意,ArcCatalog 只能連接32位的 Oracle 客戶端,我安裝的是32位的 Oracle 11g 客戶端。

導(dǎo)入數(shù)據(jù)

  1. 成功連接到 Oracle 之后在數(shù)據(jù)庫連接下就會(huì)看到一個(gè)新建的連接,右鍵,導(dǎo)入→要素類(單個(gè)),打開如下的窗口。


    導(dǎo)入要素窗口
  2. 介紹幾個(gè)關(guān)鍵字段的含義:
  • 輸入要素:就是要導(dǎo)入的矢量數(shù)據(jù),這里選擇的是 .shp 文件(示例數(shù)據(jù)將會(huì)在文末給出)。注意文件名中不能包含中文。
  • 輸出要素類:數(shù)據(jù)將會(huì)導(dǎo)入到這個(gè)字段指定的表中。
  • 配置關(guān)鍵字:選擇 SDO_GEOMETRY,這是 Oracle Spatial 提供的空間數(shù)據(jù)類型。
  1. 點(diǎn)擊確定,右鍵連接,選擇刷新,導(dǎo)入成功的話就會(huì)看到一個(gè)新生成的表,表名就是剛才在輸出要素類中給的值。

用 Java API 進(jìn)行基本的空間查詢

實(shí)現(xiàn) Domain 類,封裝數(shù)據(jù)

??前面已經(jīng)提過,Oracle Spatial 用 SDO_GEOMETRY 類型來表示空間數(shù)據(jù),Java API 中對(duì)應(yīng)的類是 oracle.spatial.geometry.JGeometry。根據(jù)表中的字段,設(shè)計(jì)如下的 JavaBean 用來封裝數(shù)據(jù):

// 封裝鐵路信息的類
public class RailWay {
    private int objectId;
    private JGeometry shape;
    private double fNode;
    private double tNode;
    private double lPoly;
    private double rPoly;
    private int gbCode;
    private String name;
    private String pinYin;
    private double length_m;

    public int getObjectId() {
        return objectId;
    }

    public void setObjectId(int objectId) {
        this.objectId = objectId;
    }

    public JGeometry getShape() {
        return shape;
    }

    public void setShape(JGeometry shape) {
        this.shape = shape;
    }

    public double getfNode() {
        return fNode;
    }

    public void setfNode(double fNode) {
        this.fNode = fNode;
    }

    public double gettNode() {
        return tNode;
    }

    public void settNode(double tNode) {
        this.tNode = tNode;
    }

    public double getlPoly() {
        return lPoly;
    }

    public void setlPoly(double lPoly) {
        this.lPoly = lPoly;
    }

    public double getrPoly() {
        return rPoly;
    }

    public void setrPoly(double rPoly) {
        this.rPoly = rPoly;
    }

    public int getGbCode() {
        return gbCode;
    }

    public void setGbCode(int gbCode) {
        this.gbCode = gbCode;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPinYin() {
        return pinYin;
    }

    public void setPinYin(String pinYin) {
        this.pinYin = pinYin;
    }

    public double getLength_m() {
        return length_m;
    }

    public void setLength_m(double length_m) {
        this.length_m = length_m;
    }

    @Override
    public String toString() {
        return this.name + ",編號(hào)" + this.gbCode + ",長(zhǎng)度為" + this.length_m + "m";
    }
}

實(shí)現(xiàn) DAO 類,提供 CRUD 接口

??這里只舉例如何進(jìn)行查詢。

// DAO 類,提供 CRUD 接口
public class RailWayDao {   
    private static NamedParameterJdbcTemplate namedTempl;
    
    // 建立數(shù)據(jù)連接
    static { 
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("oracle.jdbc.OracleDriver");
        dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:orcl");
        dataSource.setUsername("");
        dataSource.setPassword("");
        namedTempl =  new NamedParameterJdbcTemplate(dataSource);
    }
    
    // 查詢指定名字的鐵路,返回結(jié)果只有一個(gè)
    public RailWay getRailWay(String name) {
        String sql = "select * from railwayorcl where name = :name";
        Map<String,String> param = new HashMap<>();
        param.put("name", name);
        // 需要自己實(shí)現(xiàn) RowMapper
        return this.namedTempl.queryForObject(sql, param, (rs,rowNum) -> {
            RailWay r = new RailWay();
            r.setObjectId(rs.getInt("objectId"));
            r.setShape(JGeometry.load((STRUCT)rs.getObject("shape")));
            r.setfNode(rs.getDouble("fNode_"));
            r.settNode(rs.getDouble("tNode_"));
            r.setlPoly(rs.getDouble("lPoly_"));
            r.setrPoly(rs.getDouble("rPoly_"));
            r.setGbCode(rs.getInt("gbCode"));
            r.setName(rs.getString("name"));
            r.setPinYin(rs.getString("pinYin"));
            r.setLength_m(rs.getDouble("length_m"));
            return r;
        });
    }
    
    //查詢指定名字的鐵路,查詢結(jié)果不止一個(gè)
    public List<RailWay> getRailWays(String name) {
        String sql = "select * from railwayorcl where name = :name";
        Map<String,String> param = new HashMap<>();
        param.put("name", name);
        //需要自己實(shí)現(xiàn) RowMapper
        return this.namedTempl.query(sql, param, (rs,rowNum) -> {
            RailWay r = new RailWay();
            r.setObjectId(rs.getInt("objectId"));
            r.setShape(JGeometry.load((STRUCT)rs.getObject("shape")));
            r.setfNode(rs.getDouble("fNode_"));
            r.settNode(rs.getDouble("tNode_"));
            r.setlPoly(rs.getDouble("lPoly_"));
            r.setrPoly(rs.getDouble("rPoly_"));
            r.setGbCode(rs.getInt("gbCode"));
            r.setName(rs.getString("name"));
            r.setPinYin(rs.getString("pinYin"));
            r.setLength_m(rs.getDouble("length_m"));
            return r;
        });
    }
    
    // 查詢指定名字的鐵路的結(jié)點(diǎn)坐標(biāo)
    public double[] getCoords(String name) {
        double[] coords = new double[0];
        RailWay r = getRailWay(name);
        coords = r.getShape().getOrdinatesArray();
        return coords;
    }
}

??需要注意的是,從數(shù)據(jù)庫查詢到的空間數(shù)據(jù)是 oracle.sql.STRUCT 類型的,而在前面設(shè)計(jì)的 RailWay 類中,空間數(shù)據(jù)是 JGeometry 類型的,所以這里需要手動(dòng)進(jìn)行轉(zhuǎn)換。因此,必須自己實(shí)現(xiàn)一個(gè) RowMapper :

    public RailWay getRailWay(String name) {
        String sql = "select * from railwayorcl where name = :name";
        Map<String,String> param = new HashMap<>();
        param.put("name", name);
        // RowMapper 接口只有一個(gè) mapRow 方法,所以使用了 lambda 表達(dá)式
        return this.namedTempl.queryForObject(sql, param, (rs,rowNum) -> {
            RailWay r = new RailWay();
            r.setObjectId(rs.getInt("objectId"));
            //將 STRUCT 轉(zhuǎn)換成 JGeometry
            r.setShape(JGeometry.load((STRUCT)rs.getObject("shape"))); 
            r.setfNode(rs.getDouble("fNode_"));
            r.settNode(rs.getDouble("tNode_"));
            r.setlPoly(rs.getDouble("lPoly_"));
            r.setrPoly(rs.getDouble("rPoly_"));
            r.setGbCode(rs.getInt("gbCode"));
            r.setName(rs.getString("name"));
            r.setPinYin(rs.getString("pinYin"));
            r.setLength_m(rs.getDouble("length_m"));
            return r;
        });
    }

示例數(shù)據(jù) 密碼:9b1u
Oracle Spatial Java API 的各種 jar 包在 %ORACLE_HOME%\md\jlib 目錄下。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ORA-13000: 維數(shù)超出范圍 ORA-13001: 維數(shù)不匹配錯(cuò)誤 ORA-13002: 指定的級(jí)別超出范圍...
    thinkact閱讀 20,024評(píng)論 1 5
  • 動(dòng)與靜切換自如 人在特累的時(shí)候,反而是應(yīng)該停下來的時(shí)候,靜靜思考,休養(yǎng)生息,一定會(huì)有更大的智慧迸發(fā)。 多聽聽生活的...
    landi說閱讀 483評(píng)論 0 1
  • 一、現(xiàn)如今我了解到的有這三種基于網(wǎng)絡(luò)應(yīng)用的架構(gòu)風(fēng)格: 1、RPC架構(gòu)風(fēng)格:SOAP就是RPC風(fēng)格的一種架構(gòu)。過程是...
    我的馬兒有些瘦閱讀 504評(píng)論 0 0
  • 為什么你的朋友圈設(shè)置只能看最近三天?因?yàn)檫@樣大家就不知道我多久沒發(fā)朋友圈啦! 不知道你有沒有注意到一個(gè)現(xiàn)象,大家發(fā)...
    生生y閱讀 6,077評(píng)論 0 3
  • 星期一就要考試?yán)?!我?zhǔn)備早點(diǎn)睡覺,養(yǎng)足精神,迎接星期一的考試。 星期一早上,我迷迷糊糊的醒來。剛起...
    LXY李星毅閱讀 223評(píng)論 0 2

友情鏈接更多精彩內(nèi)容