7.2 在Java中操作几何体
如你所见,空间对象以SDO_GEOMETRY类型存储在数据库表中。要在Java中对其进行处理,必须首先使用JDBC从数据库中读取它们,然后把它们映射为Java类。
把SDO_GEOMETRY类型映射为Java类是比较简单的,这都归功于Oracle Spatial提供的API接口。API本身是比较简单的:它有一个主要的包(ry),该包中包含两个主要的 类(JGeometry和J3D_Geometry)。这个API在Oracle Databa 11g中被显著地加强了。它现在包含许多几何体的处理函数,同时也包含可以在一些标准格式(GML、WKT和ESRI等格式)间进行几何体格式转换的工具 函数。这些工具都位于oracle. spatial.util包中。
Oracle Spatial的Java API由位于Oracle安装目录($ORACLE_HOME/md/jlib )下的两个JAR文件(sdoapi.jar和sdoutl.jar)组成。要在应用中使用API,须记得要在类路径(classpath)中包含上述目 录。你也需要JDBC驱动和XML解析器(仅用于处理GML)。下面是在Windows环境中你的类路径的设置:
1.C:\>t classpath=.;%ORACLE_HOME%\jdbc\lib\ojdbc14.jar;
2.%ORACLE_HOME%\md\jlib\sdoapi.jar;%ORACLE_HOME%\md\jlib\sdoutl.jar;
3.%ORACLE_HOME%\lib\xmlparrv2.jar;
Oracle Spatial Java API 的文档 (Javadoc) 在Oracle文档全集中有,也可以在你的Oracle安装目录中的两个文档$ORACLE_HOME/md/doc/sdoapi.zip和sdoutl.zip中找到。
在Apress站点中可以找到大量的关于如何读、写和处理几何体的Java完整示例。表7-1中列出了这些程序。
表7-1 程序示例
程 序 | 返 回 信 息 |
SdoPrint.java | 打印出任意表中几何体的结构 |
SdoExport.java | 把表中一部分或全部的几何体导 出到格式为WKT、WKB、 GML或其他的文件 |
SdoImport.java | 把先前导出的几何体导入到表中 |
| |
7.2.1 使用JGeometry类
Java中操作几何体的主要工具就是JGeometry类。它使你可以对数据库中的几何体进行读写,同时也可以对几何体进行检查,创建新的几何体和对这些几何体进行一系列的转换。
1. 几何体的读写
当你用SQL的SELECT语句读取对象类型(如SDO_GEOMETRY类型)时,JDBC返回一个Java结构-- 更精确地说,是oracle.sql.STRUCT对象。在写一个对象的时候(用INSERT或UPDATE语句),你仍需要通过 oracle.sql.STRUCT对象来传递。对STRUCT的解码和构造都是相当复杂的,而Oracle Spatial Java API(JGeometry类)的主要目标就是使得这种操作变得简单。
JGeometry类提供了两种把STRUCT转换成JGeometry对象的方法:恒星star
大学生英语作文网load()方法用于读入STRUCT,返回JGeometry对象。当你对由SELECT语句返回的几何体进行转换的时候,用该方法。
store()方法与load()方法相反。它把JGeometry对象转换成可以通过INSERT或UPDATE语句写回数据库中的STRUCT对象。
图7-3展示了转换的过程。
|
(点击查看大图)图7-3 在Java中对几何体的读写 |
|
在Oracle Databa 11g中,load()和store()方法得到了强化,以提供自己的为几何体对象而优化的序列化(pickling) 及反序列化(unpickling)方法。因此它们应当执行得更好。对于读取一个几何体,首先要把这个对象以字节数组的形式读入,然后把这个数组传递给 load()方法。图7-4展示了这个过程。
如何提升进店率 |
图7-4 用优化的"序列化"工具在Java中对几何体进行读写 |
|
下面的这个例子,首先用结果集的getObject()方法,把各行的几何体对象提取为STRUCT类型,然后使用JGeometry的静态方法load()把它转换成JGeometry对象。
1.a什么意思STRUCT dbObject = (STRUCT)&Object(1);
2.JGeometry geom = JGeometry.load(dbObject);
要使用优化的反序列化工具(unpickler),首先使用结果集的getBytes( )方法提取几何体到一个字节数组中。然后再次使用JGeometry的静态方法load()把它转换成JGeometry对象。
1.byte[] image = rs. getBytes (1);
变暖的地球
2.JGeometry geom = JGeometry.load(image);
2. 检查几何体
你现在可以用多个get()方法从几何对象中提取信息。表7-2中总结了主要的方法。在表7-3中附加的is()方法对几何体的特性进行了细化。
表7-2 JGeometry中主要的get()方法
方 法 | 返 回 信 息 |
getType() | 几何体类型 (1表示点,2表示线,依次类推) |
getDimensions() | 维度 |
getSRID() | 空间参考系ID |
getNumPoints() | 几何体中的点数 |
getPoint() | 点对象的坐标(如果几何体是点) |
getFirstPoint() | 几何体中的第一点 |
getLastPoint() | 几何体中的最后一点 |
getMBR() 专八成绩查询 | 几何体的MBR |
getElemInfo() | SDO_ELEM_INFO数组的内容 |
getOrdinatesArray() | SDO_ORDINATES数组的内容 |
getLabelPoint() | 返回SDO_POINT结构的坐标。当用来填充线 或多边形几何体时,这通常被用来当标记点 |
getJavaPoint() | 对一个单点对象来说,以java.awt. geom.Point2D对象的形式返回点坐标 |
getJavaPoints() | 对多点对象来说,返回一个java.awt. geom.Point2D 对象数组 |
getElements() | 得到一个JGeometryossine对象数组,每个对 象都表示几何体的一个元素 |
getElementAt() | 以JGeometry格式提取几何体的一个元素 |
createShape() | 把几何体转换成java.awt.Shape对象, 为绘制和使用java.awt包中的工具做准备 |
| |
表7-3 主要的JGeometry is()方法
方 法 | 返 回 信 息 |
isPoint() | 是不是点 |
isOrientedPoint() | 是不是有向点 |
isCircle() | 是不是圆 |
isGeodeticMBR() | 是不是大地测量学的MBR volleyball |
isMultiPoint() | 是不是多点 |
isRectangle() | 是不是矩形 |
hasCircularArcs() | 几何体中是否包含弧 |
isLRSGeometry() | 是不是一个线性参照的几何体 |
| |
表7-2中的两个方法(getElements()和getElementAt())可以对复杂几何体的结构进行检查:你可以提取独立的元素作为单 独的JGeometry对象。第一个方法返回所有元素到独立的JGeometry对象数组中。第二个方法返回一个指定元素,通过其在几何体中的位置来标 识。
警告:
对element术语的理解应参见OGC Simple Features for SQL规范。例如,一个有孔多边形被看作是一个单元素,尽管它由多个环(在Oracle概念中,每个都是一个单元素)组成。在第5章中讨论的验证函数 (VALIDATE_GEOMETRY_WITH_CONTEXT()和EXTRACT())表现出同样的方式。这就意味着getElements()方 法不允许你从一个有孔多边形中提取孔。
警告:
元素的编号方式是从1开始的,而不是0。
3. 创建几何体
向数据库中写入几何体(用INSERT或UPDATE语句)要求先创建一个新的JGeometry对象,并用JGeometry.store()方 法把它转换成STRUCT。然后把STRUCT传递给INSERT或UPDATE语句。同load()方法一样,也可以使用速度更快的空间序列化工具。图 7-3和7-4展示了这两个方法。
下面是这两个方法的例子。首先用JGeometry的静态方法store()把它转换为STRUCT,然后用tObject()方法把它插入到准备好的SQL语句中。
1.STRUCT dbObject = JGeometry.store (geom, dbConnection);
2.stmt.tObject (1,dbObject);
使用优化的序列化工具除了与store()方法的参数顺序相反以外,其他的都一样:先是定义数据库连接对象,然后是创建JGeometry对象。
1.STRUCT dbObject = JGeometry.store (dbConnection, geom);
2.stmt.tObject (1,dbObject);
有两种方法可以构造新的JGeometry对象。一种是使用表7-4中的构造函数。另一种方法是用静态的方法来创建不同的几何体。表7-5列出了这些方法。
表7-4 JGeometry转换器
构 造 函 数 | 目 的 |
JGeometry (double x, double y, int srid) | 构造点 |
JGeometry (double x, double y, double z, int srid) | 构造三维点 |
JGeometry (double minX, double minY, double maxX, double maxY, int srid) | 创建矩形hrb |
JGeometry (int gtype, int srid, int[] elemInfo, double[] ordinates) | 构造一般几何体 |
| |
表7-5 静态JGeometry创建方法
创 建 方 法 | 目 的 |
createPoint(double[] coord, int dim, int srid) | 创建点 |
createLinearLineString(double[] coords, int dim, int srid) | 创建简单线串 |
createLinearPolygon(double[] coords, int dim, int srid) | 创建简单多边形 |
createMultiPoint(java.lang.Object[] coords, int dim, int srid) | 创建多重点对象 |
createLinearMultiLineString(java.lang.Object[] coords, int dim, int srid) | 创建多重线串对象 |
createLinearPolygon(java.lang.Object[] coords, int dim, int srid) | 创建多重多边形 |
createCircle(double x1, double y1, double x2, double y2, double x3, double y3, int srid) | 用圆上三点创建圆 |
createCircle(double x, double y, double radius, int srid) | 手续费英语用中心和半径创建圆 |
| |
4. 修改存在的几何体