Mybatis映射Oracle Spatial和Jgeometry


引子

最近要用到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写的,格式可能会有点乱。

转载自:https://blog.csdn.net/zhaowenbo168/article/details/46943509

You may also like...

退出移动版