Mybatis映射Oracle Spatial和Jgeometry

来源:互联网 发布:太原师范学院教务网络 编辑:程序博客网 时间:2024/06/18 13:25

引子

最近要用到Oracle Spatial中SDO_Geometry数据结构,因为SDO_Geometry可以存储点、线、面等几何图形,关于SDO_Geometry的介绍网上很多,此处不再赘述。本文要介绍的是在java中实现对Oracle中的SDO_Geometry类型的字段的读写。

创建Oracle Spatial空间索引

创建Oracle的空间索引的例子网上很多,只列出步骤,不解释具体的原理。
1.创建表

CREATE TABLE GEOMETRY_TABLE(  ID              NUMBER,  NAME            VARCHAR2(30),  GEOMETRY        SDO_GEOMETRY,)

2.创建相应的空间元数据
元数据视图USER_SDO_GEOM_METADATA,可以select查看。

INSERT INTO USER_SDO_GEOM_METADATA VALUES('GEOMETRY_TABLE', 'GEOMETRY', MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('longitude', -180, 180, 0.005), MDSYS.SDO_DIM_ELEMENT('latitude', -90, 90, 0.005)), 8307);

USER_SDO_GEOM_METADATA视图包含的字段有TABLE_NAME,COLUMN_NAME,DIMINFO,SRID.对于SRID我们通常使用国际标准的Longitude/Latitude(8307)。使用的有很多标准,如果有兴趣的话可以去oracle的MDSYS用户下去查看,有个专门记录SRID值的表。

3.创建空间索引

CREATE INDEX GEO_INDEX ON GEOMETRY_TABLE(GEOMETRY) INDEXTYPE IS MDSYS.SPATIAL_INDEX;

Mybatis映射JGeometry和SDO_GEOMETRY

空间对象以SDO_GEOMETRY类型存储在数据库表中。要在Java中对其进行处理,必须首先使用JDBC从数据库中读取它们,然后把它们映射为Java类。Oracle Spatial提供了API接口。Oracle Spatial的Java API的jar包在Oracle安装目录($ORACLE_HOME/md/jlib )下(sdoapi.jar和sdoutl.jar),将其导入java的classpath。主要用的两个类JGeometry和J3D_Geometry,一个是二维的,一个是三维的。

在使用java读写数据库中包含SDO_GEOMETRY类型的表时可以使用JDBC来做,但是由于JDBC的缺点,所以采用Mybatis来做持久层和数据的映射。由于Mybatis不包含将JGeometry和SDO_GEOMETRY对应的TypeHandler,所以要建立自己的TypeHandler。

建立SdoGeometryTypeHandler
建立自己的Typehandler可以通过继承原始接口TypeHandler或者 BaseTypeHandler抽象类,两个差不多,我用的时通过继承原始接口TypeHandler。
在Mybatis中要实现自己的TypeHandler就需要实现Mybatis为我们提供的TypeHandler接口。在TypeHandler中定义了四个方法,下面解释这四个方法的作用:
Java代码

public interface TypeHandler<T> {      /**      * 用于定义在Mybatis设置参数时该如何把Java类型的参数转换为对应的数据库类型      * @param ps 当前的PreparedStatement对象      * @param i 当前参数的位置      * @param parameter 当前参数的Java对象      * @param jdbcType 当前参数的数据库类型      * @throws SQLException      */      void setParameter(PreparedStatement ps, int i, T parameter,             JdbcType jdbcType) throws SQLException;      /**      * 用于在Mybatis获取数据结果集时如何把数据库类型转换为对应的Java类型      * @param rs 当前的结果集      * @param columnName 当前的字段名称      * @return 转换后的Java对象      * @throws SQLException      */      T getResult(ResultSet rs, String columnName) throws SQLException;      /**      * 用于在Mybatis通过字段位置获取字段数据时把数据库类型转换为对应的Java类型      * @param rs 当前的结果集      * @param columnIndex 当前字段的位置      * @return 转换后的Java对象      * @throws SQLException      */      T getResult(ResultSet rs, int columnIndex) throws SQLException;      /**      * 用于Mybatis在调用存储过程后把数据库类型的数据转换为对应的Java类型      * @param cs 当前的CallableStatement执行后的CallableStatement      * @param columnIndex 当前输出参数的位置      * @return      * @throws SQLException      */      T getResult(CallableStatement cs, int columnIndex) throws SQLException;  }  

建立一个名叫SdoGeometryTypeHandler的TypeHandler,具体代码如下:
Java代码

package com.instance.mybatis.handler;import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import oracle.spatial.geometry.JGeometry;import oracle.sql.STRUCT;import org.apache.ibatis.type.JdbcType;import org.apache.ibatis.type.MappedJdbcTypes;import org.apache.ibatis.type.MappedTypes;import org.apache.ibatis.type.TypeHandler;@MappedTypes({JGeometry.class})@MappedJdbcTypes({JdbcType.STRUCT})//这两个Mapped也可不需要public class SdoGeometryTypeHandler implements TypeHandler<JGeometry> {    @Override    public void setParameter(PreparedStatement ps, int i, JGeometry parameter,            JdbcType jdbcType) throws SQLException {        // TODO Auto-generated method stub        STRUCT dbObject = JGeometry.store(parameter, ps.getConnection());        ps.setObject(i, dbObject);    }    @Override    public JGeometry getResult(ResultSet rs, String columnName)            throws SQLException {        // TODO Auto-generated method stub        STRUCT st = (STRUCT) rs.getObject(columnName);        if (st != null) {            return JGeometry.load(st);        }        return null;    }    @Override    public JGeometry getResult(ResultSet rs, int columnIndex)            throws SQLException {        // TODO Auto-generated method stub        STRUCT st = (STRUCT) rs.getObject(columnIndex);        if (st != null) {            return JGeometry.load(st);        }        return null;    }    @Override    public JGeometry getResult(CallableStatement cs, int columnIndex)            throws SQLException {        // TODO Auto-generated method stub        STRUCT st = (STRUCT) cs.getObject(columnIndex);        if (st != null) {            return JGeometry.load(st);        }        return null;    }}

然后我们在Mybatis的配置文件中这样注册它:

 <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" ><configuration>    <typeAliases>        <typeAlias type="oracle.spatial.geometry.JGeometry" alias="JGeometry" />        <typeAlias type="com.instance.domain.Geometry" alias="Geometry" />    </typeAliases>    <typeHandlers>        <typeHandler handler="com.albert.wen.instance.mybatis.handler.SdoGeometryTypeHandler" javaType="JGeometry" />    </typeHandlers>    <mappers>        <mapper resource="com/instance/mapper/GeometryDaoMapper.xml" />    </mappers></configuration>

下面就是GeometryDaoMapper.xml中如何使用自定义的TypeHandler了,查询和插入的SQL语句写法:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.instance.mapper.GeometryDaoMapper">    <resultMap id="defaultResultMap" type="Geometry">        <result property="id" column="id" />        <result property="name" column="name" />        <result property="geometry" column="geometry" javaType="JGeometry" jdbcType="STRUCT" />    </resultMap>    <select id="select" resultMap="defaultResultMap">        SELECT id, name, geometry FROM geometry_table    </select>    <insert id="insert" parameterType="Geometry">        INSERT INTO geometry_table(id, name, geometry) VALUES(#{id}, #{name}, #{geometry,javaType=JGeometry,jdbcType=STRUCT})    </insert></mapper>

在网上找了一下,没有找到关于Mybatis将JGeometry和Oracle中的SDO_Geometry映射的例子,所以就将自己的实例发出来和大家分享一下,还有数据库的配置是使用spring完成的。因为是第一次写博客,还是用markdown写的,格式可能会有点乱。

1 0
原创粉丝点击