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包名)

浙公网安备 33010602011771号