MyBatis 配置 typeHandlers 详解

0x00:前言参考

之前的《MyBatis 中 SqlMapConfig 配置文件详解》记了一下 MyBatis 中的核心配置文件各个标签的作用和使用场景,这篇文章细说一下配置文件中 typeHandlers 标签的详细使用。

0x01:标签介绍

在 MyBatis 的 sql 映射配置文件中,为 sql 配置的输入参数最终要从 java 类型转换成数据库能识别的类型,而从 sql 的查询结果集中获取的数据,也要从数据库的数据类型转换为对应的 Java 类型。

在 MyBatis 中,使用类型处理器(TypeHandler)将数据库获取的值以合适的方式转换为 Java 类型,或者将 Java 类型的参数转换为数据库对应的类型。

在 MyBatis 中有许多自带的类型处理器,但有时候也会满足不了开发的需求,这时候就需要配置自己的类型处理器了,而 typeHandlers 标签就是用来声明自己的类型处理器的。

0x02:编写说明

使用 typeHandlers 标签配置一个自己的类型处理器,一般需要三个步骤:编写类型处理器类,在 MyBatis 全局配置文件中配置该类型处理器,在 sql 映射配置文件中使用。

例如要编写一个将 JDBC 的 timestamp 类型与 Date 类型相互转换的类型处理器配置示例。首先编写类型处理器,一般要实现 org.apache.ibatis.type.TypeHandler 接口,接口的泛型指定要转换的 Java 参数类型,若不指定则默认为 Object 类,实现 TypeHandler 接口主要改写四个方法,如下:

public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
public String getResult(ResultSet rs,String columnName)
public String getResult(ResultSet rs,int columnIndex)
public String getResult(CallableStatement cs,int columnIndex)

setParameter 方法是在 sql 配置传入参数时(新增、删除、修改、查询)执行的操作,可以在将参数传入数据库之前在该方法中对数据类型做处理。

另外三个 getResult 方法则在数据库返回结果时,将结果信息转换为相应的 Java 类型。区别在于前两个 getResult 方法供普通 select 方法使用,一个根据字段名,一个根据字段下标来获取数据,最后一个 getResult 方法供存储过程使用,根据字段下标获取数据。

0x03:代码示例

以下代码是编写一个将 JDBC 的 timestamp 类型与 Date 类型相互转换的类型处理器配置示例:

package cn.com.mybatis.test;

import java.sql.CallableStatement;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.JdbcType;

public class DateTypeHandler implements TypeHandler<Date> {

    //转换日期类型的辅助类
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public void setParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException{
        //指定传入的Java参数对应JDBC中的数据库类型
        System.out.println("其他逻辑");
        ps.setDate(i, parameter);
        System.out.println("其他逻辑");
    }
    public Date getResult(ResultSet rs,String columnName) throws SQLException{
        System.out.println("其他逻辑");
        return rs.getDate(columnName);
    }
    public Date getResult(ResultSet rs,int columnIndex) throws SQLException{
        System.out.println("其他逻辑");
        return rs.getDate(columnIndex);
    }
    public Date getResult(CallableStatement cs,int columnIndex) throws SQLException{
        System.out.println("其他逻辑");
        return cs.getDate(columnIndex);
    }
}

之后在 MyBatis 的全局配置文件 SqlMapConfig 中使用 typeHandlers 标签来注册类型处理器,示例代码如下:

 <typeHandlers>
    <typeHandler handler="cn.com.mybatis.test.DateTypeHandler" javaType="java.util.Date" jdbcType="TIMESTAMP"/>
</typeHandlers>

然后在 sql 映射文件 xxxMapper.xml 中的 sql 语句中添加自定义的类型处理器的处理配置即可,代码示例如下:

insert into user(username,password,regdate) value(#{username},#{password},
    #{regdate,javaType=date,jdbcType=TIMESTAMP,
    typeHandler=cn.com.mybatis.test.DateTypeHandler})

如果设置了参数 regdate,就会将 Java 的 Date 类型转换为数据库需要的 timestamp 类型。另外,对于查询结果,如果定义了 resultMap 来设置结果集对象的映射,同样可以在标签内指定 javaType,jdbcType 和 typeHandler 的名称。

0x04:知识拓展

在编写自定义的类型处理器时,可以不实现 TypeHandler 接口,转而继承另一个类 org.apache.ibatis.type.BaseTypeHandler, 它是 MyBatis 的一个标准基础类型处理器类。

BaseTypeHandler 本身已经实现了 TypeHandler 接口,并继承了 TypeReferance 抽象类,在它内部简单的实现了 TypeHandler 接口中定义的四个方法的部分功能。

继承 BaseTypeHandler 类之后,可以通过改写 setNonNullParameter、getNullableResult 方法(三个)来实现类型处理器。示例代码如下:

public abstract void setNonNullParameter(PreparedStatement ps,int i,T parameter,JdbcType jdbcType)
public abstract T getNullableResult(ResultSet rs,String columnName)
public abstract T getNullableResult(ResultSet rs,int columnIndex)
public abstract T getNullableResult(CallableStatement cs,int columnIndex)

因为 BaseTypeHandler 继承 TypeReferance 抽象类,所以它本身也是一个抽象类,类中的 4 个方法也为抽象方法。

0x05:总结

MyBatis 中,其内部的类型处理器大部分都是继承上面的 4 个方法来实现的,当其内部的类型处理器无法满足开发需求时,就需要自己定义类型处理类,步骤为先编写类型处理器类,其次将该处理器类配置到全局配置文件中,最后在 sql 映射配置文件中使用即可。


更多关于代码审计、WEB渗透、网络安全的运维的知识,请关注微信公众号:发哥微课堂。


猜你喜欢

转载自blog.csdn.net/fageweiketang/article/details/80787213