mybatis maps oracle spatial JGeometry types and calls stored procedures.

There is a requirement that the latitude and longitude coordinate string is requested through http, and an oracle stored procedure is called in the background.

Because the oracle library is called, and the geometry type field of the spatial feature needs to be used, the oracle's own class library is used.
oracle.spatial.geometry.JGeometry.

I involve 4 jar packages here.
sdoapi.jar
sdotopo.jar
sdoutl.jar
sdonm.jar The

jar package generally needs to be downloaded from the Oracle official website. If there is a server side, it can generally be found in the ${ORACLE_HOME}md/jlib directory.

If mybatis wants to map to the JGeometry type, it needs to set the type to STRUCT.
It must implement the interface provided by mybatis. Refer to the blog below.
http://blog.csdn.net/zhaowenbo168/article/details/46943509

There is a problem in the above blog, that is, if you use some connection pools, when mybatis calls TypeHandler, the packaged connection cannot be forced to be converted to OracleConnection, you need to Determine whether the connection in the connection pool is a package of OracleConnection, if it needs to be unpacked, and then use the original connection to construct a STRUCT object. See the code setParameter method below.
import java.sql.*;

import oracle.jdbc.driver.OracleConnection;
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})//These two Mappeds are also not needed
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
        Connection conn = ps.getConnection();
        OracleConnection oracleConnection= null;
        if(conn.isWrapperFor(OracleConnection.class)){
            oracleConnection = conn.unwrap(OracleConnection.class);
            STRUCT dbObject = JGeometry.store(parameter, oracleConnection);
            ps.setObject(i, dbObject);
        }
        else{
            STRUCT dbObject = JGeometry.store(parameter, conn);
            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;
    }

}


The next step is to configure the xml file. mybatisconfig.xml
<?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>
    <!-- Configure the alias of the mapping class -->
    <typeAliases>

        <typeAlias alias="Usermodel" type="com.xxx.model.Usermodel"/>
        <typeAlias type="oracle.spatial.geometry.JGeometry" alias="JGeometry" />
        <typeAlias type="com.xxx.model.GeometryTest" alias="Geometry"/>

    </typeAliases>

    <typeHandlers>
        <typeHandler handler="com.xxx.config.SdoGeometryTypeHandler" javaType="JGeometry"/>
    </typeHandlers>
    <!-- Configure the path of the Mapper file-->
    <mappers>
        <mapper resource="conf/mybatis-config.xml"/>
    </mappers>
</configuration>


mybatis-config.xml: The following select id =calcost is to call the stored procedure. The parameter defined in the mapping interface is HashMap, including input parameters and output parameters.
<?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.navinfo.smap_tollgate.mapper.TollMapping">
    <!-- Query a single record-->


    <select id="usermodelByKey" parameterType="String" resultType="Usermodel">

select a.userid,a.accesskey,a.expiration  from ni_user a where to_date(a.expiration,'YYYYmmDDhh24MISS') - SYSDATE >0 AND A.accesskey = #{key}
    </select>

    <select id="calcost" parameterType="java.util.HashMap" statementType="CALLABLE">

            {call PRO_SHAPE_MATCH.PRO_TOLL_ENTRY(#{geom,mode=IN,javaType=JGeometry,jdbcType=STRUCT},
            #{s_x,mode=IN,jdbcType=DOUBLE},
            #{s_y,mode=IN,jdbcType=DOUBLE},
            #{e_x,mode=IN,jdbcType=DOUBLE},
            #{e_y,mode=IN,jdbcType=DOUBLE},
            #{buf_dis,mode=IN,jdbcType=INTEGER},
            #{cost,mode=OUT,jdbcType=DOUBLE})}

    </select>

    <select id="callProceTest" parameterType="java.util.HashMap" statementType="CALLABLE">

        {call NAVI_SHAPE_MATCH.TEST_OUT(#{x,mode=IN,jdbcType=VARCHAR},#{y,mode=OUT,jdbcType=VARCHAR})}

    </select>

    <resultMap id="defaultResultMap" type="Geometry">
        <result property="link_pid" column="link_pid" />
        <result property="geometry" column="geometry" javaType="JGeometry" jdbcType="STRUCT" />
    </resultMap>

    <select id="callGeoTest" resultMap="defaultResultMap">

        select link_pid,geometry from rd_link_test where rownum=1

    </select>

    <insert id="insert" parameterType="Geometry">
        INSERT INTO rd_link_test(link_pid, geometry) VALUES(#{link_pid}, #{geometry,javaType=JGeometry,jdbcType=STRUCT})
    </insert>

</mapper>


mapping interface:
public interface TollMapping {

     Usermodel usermodelByKey(String key);

     void calTollcost(Map<String,Object> map);

     void callProceTest(Map<String,Object> map);

     GeometryTest callGeoTest();

     void insert(GeometryTest gt);

}


Service call:
@Service
public class TollService {

    @Autowired
    TollMapping tollMapping;

 private static final int gtypeLine = 2002;

    private static final int gtypePoint = 2001;

    private static final int srid = 8307;

    private static final int[] elementInfo= new int[]{1,2,1};

    private JGeometry getGeomLineByLineString(double[] ordinArray){

        return new JGeometry(gtypeLine,srid,elementInfo,ordinArray);
    }

private double getCostByMap(double[] ordinArray,double s_x,double s_y,double e_x,double e_y){
        Map<String,Object> gMap = new HashMap<>();
        gMap.put("geom",getGeomLineByLineString(ordinArray));
        gMap.put("s_x",s_x);
        gMap.put("s_y",s_y);
        gMap.put("e_x",e_x);
        gMap.put("e_y",e_y);
        gMap.put("buf_dis",80);
        return getToll(gMap);
    }



    private double getToll(Map<String,Object> map){
//        try {
//            return getTollCostFeeJbdc(map);
//        }
//        catch (Exception e){
// e.printStackTrace ();
//            return 0;
//        }
        tollMapping.calcost (map);
        return (double)map.get("cost");
    }
}


After calling calcost, the value obtained by the output parameter is naturally mapped to the map.

The following is the stored procedure related to calling geometry in jdbc mode.

private double getTollJbdc(Map<String,Object> map) throws SQLException, ClassNotFoundException {

        String url = "jdbc:oracle:thin:@" + "192.168.1.120" + ":" + 1521 + ":" + "orcl";
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(url, "test", "1");

        String procedure = "{call PRO_SHAPE_MATCH.PRO_TOLL_ENTRY(?,?,?,?,?,?,?)}";

        CallableStatement cstmt = conn.prepareCall(procedure);

        OracleConnection oc = (OracleConnection) cstmt.getConnection();

        STRUCT struct = JGeometry.store((JGeometry) map.get("geom"),oc);
        double tocost =0;
        try {
            cstmt.setObject(1, struct);

            cstmt.setDouble(2, (double) map.get("s_x"));
            cstmt.setDouble(3, (double) map.get("s_y"));
            cstmt.setDouble(4, (double) map.get("e_x"));
            cstmt.setDouble(5, (double) map.get("e_y"));
            cstmt.setInt(6,(int)map.get("buf_dis"));
            cstmt.registerOutParameter(7, Types.DOUBLE);

            cstmt.executeUpdate();

            tocost = cstmt.getDouble(7);
        }catch (Exception e){
            e.printStackTrace ();
        }
        finally {
            cstmt.close();
            conn.close();
        }

        return tocost;

    }

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326926071&siteId=291194637