实际应用开发中的难免会有一些需求要自定义一个TypeHandler ,比如这样一个需求:前端传来的性别是 男, 女,但是数据库定义的字段却是tinyint 类型( 1:男 2:女)。此时可以自定义一个年龄的类型处理器,进行转换。
定义TypeHandler
package com.mtaite.study.mybatis.handler;
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 org.springframework.util.StringUtils;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@MappedJdbcTypes(JdbcType.INTEGER)
@MappedTypes(String.class)
public class GenderTypeHandler extends BaseTypeHandler {
//设置参数,这里将Java的String类型转换为JDBC的Integer类型
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.toString().equals("男")? 1:2);
}
// 以下三个参数都是将查询的结果转换
@Override
public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getInt(columnName)==1?"男":"女";
}
@Override
public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return rs.getInt(columnIndex)==1?"男":"女";
}
@Override
public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return cs.getInt(columnIndex)==1?"男":"女";
}
}
注意点:
首先看insert语句,我们需要处理的是gender字段,因此在gender后加上typeHandler=com.mtaite.study.mybatis.handler.GenderTypeHandler;对于#{id},jdbcType=INTEGER不要填写,因为自定义的typerHandler中加了下面两个注解:@MappedJdbcTypes(JdbcType.INTEGER)和@MappedTypes(String.class),这两个注解表示JdbcType为INTEGER时,会使用此handler,所以如果有字段增加了【jdbcType=INTEGER】的话,id也会被转义。
再看select语句,sql和普通的没有区别,但是resultMap中的gender映射加了typeHandler=com.mtaite.study.mybatis.handler.GenderTypeHandler,代表此字段在转换成实体对象时会被handler处理,此外其他字段的映射jdbcType不写,保持缺省,如果是【jdbcType=INTEGER】也会被处理。
配置Mybatis配置文件
配置mapper的xml文件中的字段
通过上面的配置就可以实现性别字段的数据转换了,可以拿源代码试试哦。
源码中如何执行TypeHandler
既然会使用TypeHandler 了,那么肯定要知道其中的执行原理了,在Mybatis中类型处理器是如何在JDBC 类型和Java 类型进行转换的,下面的将从源码角度详细介绍。
入参如何转换
肯定是发生在设置参数的过程中,详细的代码在PreparedStatementHandler 中的parameterize() 方法中,这个方法就是设置参数的方法。源码如下:
实际执行的是DefaultParameterHandler 中的setParameters 方法,如下:
从上面的源码中可以知道: typeHandler.setParameter(ps, i + 1,value, jdbcType); 就是调用类型处理器中的设置参数的方法,将Java 类型转换为JDBC 类型。
结果如何转换
这一过程肯定是发生在执行查询语句的过程中,其中的ResultSetHandler 这个组件就是对查询的结果进行处理的,那么肯定是发生在这一组件中的某个方法。 在PreparedStatementHandler 执行查询结束之后,调用的是ResultSetHandler 中的handleResultSets() 方法,对结果进行处理,如下:
最终是在DefaultResultSetHandler 中的getPropertyMappingValue() 方法中调用了TypeHandler 中的getResult() 方法,如下:
扩展:Mybatis提供了许多默认处理器
想想这个功能还可以用于什么场景呢?
本文暂时没有评论,来添加一个吧(●'◡'●)