美文网首页Java 杂谈
Oracle Spatial Java API 简介

Oracle Spatial Java API 简介

作者: maxwellhertz | 来源:发表于2018-06-22 18:21 被阅读0次

    本文简要介绍如何使用 Spring JDBC 进行基本的空间查询。

    数据的准备

      将空间数据存入 Oracle Spatial 的方法有很多种,最基本的一种方法就是直接用 SQL 语句插入数据,但这种方法效率太低,而且极易出错。我个人较为喜欢也最常使用的一种方法是借助现成的 GIS 软件导入数据。下面简要介绍如何使用 ArcCatalog 将矢量数据导入 Oracle Spatial。

    连接数据库

    1. 在 ArcCatalog 的目录树中,找到数据库连接,展开后有一个添加数据库连接,双击之后就会打开如下的窗口:


      数据库连接窗口
    2. 按照图中的示范填写相关属性,实例这一项的格式是 主机:端口/数据库实例名。点击确定,然后就会连接到 Oracle。注意,ArcCatalog 只能连接32位的 Oracle 客户端,我安装的是32位的 Oracle 11g 客户端。

    导入数据

    1. 成功连接到 Oracle 之后在数据库连接下就会看到一个新建的连接,右键,导入→要素类(单个),打开如下的窗口。


      导入要素窗口
    2. 介绍几个关键字段的含义:
    • 输入要素:就是要导入的矢量数据,这里选择的是 .shp 文件(示例数据将会在文末给出)。注意文件名中不能包含中文。
    • 输出要素类:数据将会导入到这个字段指定的表中。
    • 配置关键字:选择 SDO_GEOMETRY,这是 Oracle Spatial 提供的空间数据类型。
    1. 点击确定,右键连接,选择刷新,导入成功的话就会看到一个新生成的表,表名就是刚才在输出要素类中给的值。

    用 Java API 进行基本的空间查询

    实现 Domain 类,封装数据

      前面已经提过,Oracle Spatial 用 SDO_GEOMETRY 类型来表示空间数据,Java API 中对应的类是 oracle.spatial.geometry.JGeometry。根据表中的字段,设计如下的 JavaBean 用来封装数据:

    // 封装铁路信息的类
    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 + ",编号" + this.gbCode + ",长度为" + this.length_m + "m";
        }
    }
    

    实现 DAO 类,提供 CRUD 接口

      这里只举例如何进行查询。

    // DAO 类,提供 CRUD 接口
    public class RailWayDao {   
        private static NamedParameterJdbcTemplate namedTempl;
        
        // 建立数据连接
        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);
        }
        
        // 查询指定名字的铁路,返回结果只有一个
        public RailWay getRailWay(String name) {
            String sql = "select * from railwayorcl where name = :name";
            Map<String,String> param = new HashMap<>();
            param.put("name", name);
            // 需要自己实现 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;
            });
        }
        
        //查询指定名字的铁路,查询结果不止一个
        public List<RailWay> getRailWays(String name) {
            String sql = "select * from railwayorcl where name = :name";
            Map<String,String> param = new HashMap<>();
            param.put("name", name);
            //需要自己实现 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;
            });
        }
        
        // 查询指定名字的铁路的结点坐标
        public double[] getCoords(String name) {
            double[] coords = new double[0];
            RailWay r = getRailWay(name);
            coords = r.getShape().getOrdinatesArray();
            return coords;
        }
    }
    

      需要注意的是,从数据库查询到的空间数据是 oracle.sql.STRUCT 类型的,而在前面设计的 RailWay 类中,空间数据是 JGeometry 类型的,所以这里需要手动进行转换。因此,必须自己实现一个 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 接口只有一个 mapRow 方法,所以使用了 lambda 表达式
            return this.namedTempl.queryForObject(sql, param, (rs,rowNum) -> {
                RailWay r = new RailWay();
                r.setObjectId(rs.getInt("objectId"));
                //将 STRUCT 转换成 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;
            });
        }
    

    示例数据 密码:9b1u
    Oracle Spatial Java API 的各种 jar 包在 %ORACLE_HOME%\md\jlib 目录下。

    相关文章

      网友评论

        本文标题:Oracle Spatial Java API 简介

        本文链接:https://www.haomeiwen.com/subject/eqxlyftx.html