自定义typeHandler
在大部分的场景下,MyBatis的typeHandler就能应付一般的场景,但是有时候不够用。比如使用枚举的时候,枚举有特殊的转化规则,这个时候需要自定义typeHandler进行处理它。
从系统定义的typeHandler可以知道,要实现typeHandler就需要去实现接口typeHandler,或者继承BaseTypeHandler(实际上,BaseTypeHandler实现了typeHanlder接口)。这里我们仿造一个StringTypeHandler来实现一个自定义的typeHandler——MyTypeHandler,它只是用于实现接口typeHandler,如代码清单4-13所示。
代码清单4-13:MyTypeHandler
package com.xc.util.typehandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; import org.apache.ibatis.type.TypeHandler; import org.apache.log4j.Logger; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; //@MappedTypes(String.class) //@MappedJdbcTypes(JdbcType.VARCHAR) public class MyTypeHandler implements TypeHandler<String> { // Logger logger = Logger.getLogger(MyTypeHandler.class); private static Logger log = Logger.getLogger(MyTypeHandler.class); @Override public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { log.info("设置string参数【" + parameter + "】"); ps.setString(i, parameter); } @Override public String getResult(ResultSet rs, String columnName) throws SQLException { String result = rs.getString(columnName); log.info("读取string参数1【" + result + "】"); return result; } @Override public String getResult(ResultSet rs, int columnIndex) throws SQLException { String result = rs.getString(columnIndex); log.info("读取string参数2【" + result + "】"); return result; } @Override public String getResult(CallableStatement cs, int columnIndex) throws SQLException { String result = cs.getString(columnIndex); log.info("读取string参数3【" + result + "】"); return result; } }
定义的typeHandler泛型为String,显然我们要把数据库的数据类型转化为String型,然后实现设置参数和获取结果集的方法。但是这个时候还没有启用typeHandler,它还需要做如代码清单4-14所示的配置。
数据类型转化为String型,然后实现设置参数和获取结果集的方法。但是这个时候还没有启用typeHandler,它还需要做如下图所示的配置。配置完成后系统才会读取它,这样注册后,当jdbcType和javaType能与MyTypeHandler对应的时候,它就会启动MyTypeHandler。
如上图1处:
配置MyTypeHandler与jdbcType和javaType
如上2幅图的2处:
使用包扫描的形式,只是这样就没法指定jdbcType和javaType了,不过我们可以使用注解来处理它们。
有时候还可以显式启用typeHandler
注意,要么指定了与自定义typeHandler一致的jdbcType和javaType,要么直接使用typeHandler指定具体的实现类。在一些因为数据库返回为空导致无法断定采用哪个typeHandler来处理,而又没有注册对应的javaType的typeHandler时,MyBatis无法知道使用哪个typeHandler转换数据,我们可以采用这样的方式来确定采用哪个typeHandler处理,这样就不会有异常出现了。