Mybatis中的TypeHandler-测试

1.TypeHandler概念 
TypeHandler,类型转换器,在mybatis中用于实现java类型和JDBC类型的相互转换.mybatis使用prepareStatement来进行参数设置的时候,需要通过typeHandler将传入的java参数设置成合适的jdbc类型参数,这个过程实际上是通过调用PrepareStatement不同的set方法实现的;在获取结果返回之后,也需要将返回的结果转换成我们需要的java类型,这时候是通过调用ResultSet对象不同类型的get方法时间的;所以不同类型的typeHandler其实就是调用PrepareStatement和ResultSet的不同方法来进行类型的转换,有些时候会在调用PrepareStatement和ResultSet的相关方法之前,可以对传入的参数进行一定的处理. 
当我们没有指定typeHandler的时候mybatis会根据传入参数的类型和返回值的类型调用默认的typeHandler进行处理.对于一个typeHandler需要配置java类型(javaType)和JDBC类型(jdbcType),typeHandler的作用就是实现这两种类型的转换,在传入的参数为指定的Java类型时,将其转换为指定的JDBC类型,当返回值为指定JDBC类型时将其转换为配置的Java类型.

2.mybatis默认定义的TypeHandler 
mybatis默认定义了一批TypeHandler,正常情况下这些TypeHandler就可以满足我们的使用了.mybatis通过TypeHandlerRegister来管理TypeHandler 

3.使用自定义TypeHandler

示例代码:

import lombok.extern.slf4j.Slf4j;
import oracle.sql.DATE;
import oracle.sql.TIMESTAMP;
import oracle.sql.TIMESTAMPLTZ;
import oracle.sql.TIMESTAMPTZ;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.*;

@MappedTypes({Object.class})
@MappedJdbcTypes({JdbcType.TIMESTAMP})
@Slf4j
@Component
public class MyObjectTypeHandle extends BaseTypeHandler<Object> {

    public MyObjectTypeHandle(){
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        ps.setObject(i,parameter);
    }

    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
        try {
            Object result = rs.getObject(columnName);
            return result==null?null:dealResult(result);
        } catch (SQLException e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return null;
        }
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        try {
            Object result = rs.getObject(columnIndex);
            return result==null?null:dealResult(result);
        } catch (SQLException e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return null;
        }
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        try {
            Object result = cs.getObject(columnIndex);
            return result==null?null:dealResult(result);
        } catch (SQLException e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return null;
        }
    }

    private Object dealResult(Object result) throws SQLException{
        if (result instanceof TIMESTAMP) {
            return ((TIMESTAMP) result).timestampValue().getTime();
        }else if(result instanceof DATE){
            return new Date(((DATE)result).dateValue().getTime());
        }else if(result instanceof TIMESTAMPLTZ){
            return new Date(((TIMESTAMPLTZ)result).dateValue().getTime());
        }else if(result instanceof TIMESTAMPTZ){
            return new Date(((TIMESTAMPTZ)result).dateValue().getTime());
        }else{
            return result;
        }
    }
}
import com.alibaba.fastjson.serializer.ClobSeriliazer;
import com.itc.lib.utils.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import oracle.jdbc.OraclePreparedStatement;
import oracle.sql.BLOB;
import oracle.sql.CLOB;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import javax.sql.rowset.serial.SerialClob;
import java.io.IOException;
import java.io.Writer;
import java.sql.*;

//这个注解定义的是JdbcType类型,这里的类型不可自己随意定义,必须要是枚举类org.apache.ibatis.type.JdbcType所枚举的数据类型
@MappedJdbcTypes({JdbcType.CLOB,JdbcType.BLOB  })
//这里定义的是JavaType的数据类型,描述了哪些Java类型可被拦截
@MappedTypes({String.class})
@Slf4j
@Component
public class TypeHandler extends BaseTypeHandler<String> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
       try{
           BLOB blob = BLOB.getEmptyBLOB();
           blob.setBytes(parameter.getBytes());
           ps.setBlob(i,blob);
       }catch (Exception e){
           log.error(e.getMessage(),e);
       }
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        if (rs.wasNull())
            return null;
        //解决增加异常,这样做是因为直接放入时操作的是原素组,导致不能增删操作,所以要重新创建一个
       try{
           Clob clob = rs.getClob(columnName);
           return clob == null ? "" : clob.getSubString(1, (int) clob.length());
       }catch (Exception e){
           Blob blob = rs.getBlob(columnName);
           return blob == null ? "" : new String(blob.getBytes(1, (int) blob.length()));
       }
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        if (rs.wasNull())
            return null;
        //解决增加异常,这样做是因为直接放入时操作的是原素组,导致不能增删操作,所以要重新创建一个
        if("oracle.jdbc.OracleClob".equals(rs.getMetaData().getColumnClassName(columnIndex))){
            Clob clob = rs.getClob(columnIndex);
            return clob == null ? "" : clob.getSubString(1, (int) clob.length());
        }else {
            
            Blob blob = rs.getBlob(columnIndex);
            return blob == null ? "" : new String(blob.getBytes(1, (int) blob.length()));
        }
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        if (cs.wasNull())
            return null;
        //解决增加异常,这样做是因为直接放入时操作的是原素组,导致不能增删操作,所以要重新创建一个
        if("oracle.jdbc.OracleClob".equals(cs.getMetaData().getColumnClassName(columnIndex))){
            Clob clob = cs.getClob(columnIndex);
            return clob == null ? "" : clob.getSubString(1, (int) clob.length());
        }else {
            
            Blob blob = cs.getBlob(columnIndex);
            return blob == null ? "" : new String(blob.getBytes(1, (int) blob.length()));
        }
    }
}

在字段上使用生效:

@TableField(value = "XXX", typeHandler = TypeHandler.class)

 或者(未添加@Component注解时可以生效):

在bootstrap.properties中添加:

mybatis-plus.type-handlers-package=com.xxx.typehandler(com.xxx.typehandler是l包名)

  

posted @ 2020-12-13 11:45  快乐的额  阅读(277)  评论(0)    收藏  举报