mybatis自定义typeHandler

1、项目问题:

  我们项目中有一个字段是存地址位置的,数据库采用自定义的类型,是一个多参数类型。该类型共又7个数字类型的字段,其中有4个是固定的,其中两个为2001,8307 ,另外两个为空。另外三个是保存x,y,z经纬度的值。

这种多值参数字段,mybatis会默认解析成Struct类型。但是如果一旦开启mybatis的缓存模式。项目就会报错。

为此,我去Github上mybatis项目组发了issue,得到了回答。

具体请看 :

https://github.com/mybatis/mybatis-3/issues/1152

2、如何实现并解决问题:

    1)定义处理类型:

package com.wcs.wms.task.util.typehandler;

import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Struct;
import java.util.List;

@Getter
@Setter
public class StructType implements Serializable{

    private static final long serialVersionUID = 7586786691581809590L;
    private BigDecimal taskSdoGtype;
    private BigDecimal taskSdosrid;
    private BigDecimal taskSdoPointX;
    private BigDecimal taskSdoPointY;
    private BigDecimal taskSdoPointZ;
    private List<BigDecimal> taskSdoOrdinates = null;
    private List<BigDecimal> taskSdoElemInfo = null;

    public StructType(){

    }

    public StructType(Struct struct){
        if(null != struct){
            try {
                Object[] params = struct.getAttributes();
                taskSdoGtype = (BigDecimal)params[0];
                taskSdosrid = (BigDecimal) params[1];
                if(params[2] != null){
                    Object[] geo = ((Struct) params[2]).getAttributes();
                    taskSdoPointX = (BigDecimal) geo[0];
                    taskSdoPointY = (BigDecimal) geo[1];
                    taskSdoPointZ = (BigDecimal) geo[2];
                }
            } catch (SQLException e) {
                e.printStackTrace();
                taskSdoGtype = null;
                taskSdosrid = null;
                taskSdoPointX = null;
                taskSdoPointY = null;
                taskSdoPointZ = null;
            }
        }
    }

    @Override
    public String toString() {
        return "StructType{" +
                "taskSdoGtype=" + taskSdoGtype +
                ", taskSdosrid=" + taskSdosrid +
                ", taskSdoPointX=" + taskSdoPointX +
                ", taskSdoPointY=" + taskSdoPointY +
                ", taskSdoPointZ=" + taskSdoPointZ +
                ", taskSdoOrdinates=" + taskSdoOrdinates +
                ", taskSdoElemInfo=" + taskSdoElemInfo +
                '}';
    }
}
View Code

    2)自定义类型处理器:

package com.wcs.wms.task.util.typehandler;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;

import java.sql.*;

public class StructTypeHandler implements TypeHandler<StructType> {

    public StructTypeHandler() {
    }

    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, StructType struct, JdbcType jdbcType) throws SQLException {
        preparedStatement.setObject(i,struct);
    }

    @Override
    public StructType getResult(ResultSet resultSet, String columnName) throws SQLException {
        Object object = resultSet.getObject(columnName);
        if(object instanceof Struct){
            return new StructType((Struct) object);
        }
        return null;
    }

    @Override
    public StructType getResult(ResultSet resultSet, int i) throws SQLException {
        Object object = resultSet.getObject(i);
        if(object instanceof Struct){
            return new StructType((Struct) object);
        }
        return null;
    }

    @Override
    public StructType getResult(CallableStatement callableStatement, int i) throws SQLException {
        Object object = callableStatement.getObject(i);
        if(object instanceof Struct){
            return new StructType((Struct) object);
        }
        return null;
    }
}
View Code

    3)配置类型处理器:

在mybatis-config.xml中添加:

    <typeHandlers>
        <typeHandler handler="com.wcs.wms.task.util.typehandler.StructTypeHandler" javaType="com.wcs.wms.task.util.typehandler.StructType"/>
    </typeHandlers>

    4)使用:

    在对应的mapper.xml中指定自定义类型就可以了:

    

        TASK_LOC_GEO = #{taskLocGeo,javaType=com.wcs.wms.task.util.typehandler.StructType,typeHandler=com.wcs.wms.task.util.typehandler.StructTypeHandler},

注意:此时我们的地址位置的字段已经是我们自定的类型了:

private StructType taskLocGeo;

测试,开启缓存。解决!

 

posted @ 2017-12-07 15:07  _风的线条  阅读(540)  评论(0)    收藏  举报