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