关于mybatis:mybatis之类型处理器

5次阅读

共计 2764 个字符,预计需要花费 7 分钟才能阅读完成。

本篇次要介绍一下 mybatis 的类型处理器,基于 3.4.6 版本。

知识点

  • 什么是类型处理器
  • 类型处理器的作用
  • 如何自定义类型处理器
  • 实现原理

什么是类型处理器

咱们平时在应用 mybatis 的时候比较简单,只有写一个 sql 语句,而后定义好对应的接口就能够应用了,这里就波及到一个问题:咱们调用接口的时候传入的明明是 java 的数据类型,为什么可能失常存到数据库里呢,咱们从数据库里取出来的明明是数据库中的类型,为什么可能间接在代码里拿到 java 类型呢?类型处理器就是来解决这个问题的,用 mybatis 的术语,就是 TypeHandler。

类型处理器的作用

其实下面也说到了,类型处理器的作用非常简单,总结起来就 2 种

  • 将咱们传入接口的参数转换为对应的数据库类型
  • 将数据库种查问回来的字段类型转换为对应的 java 类型

如何自定义类型处理器

咱们晓得 mybatis 内置了很多类型的处理器,这也是咱们什么都不做,间接可能实现类型转换的起因,看下目前有哪些类型处理器

能够看到,type 目录下简直全是,有趣味的能够本人去看下,这里不多做介绍。如果遇到了内置处理器无奈解决的新类型,或者咱们想要在内置的类型处理器上加一些本人的逻辑,怎么办呢?这时就须要自定义类型处理器了。这个比较简单,其实官网文档里也介绍过了,这里再具体介绍一下
1)继承 BaseTypeHandler,我这里解决的是 String 类型

public class MyTypeHandler extends BaseTypeHandler<String> {

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, String s, JdbcType jdbcType) throws SQLException {preparedStatement.setString(i, s);
    }

    @Override
    public String getNullableResult(ResultSet resultSet, String s) throws SQLException {return null;}

    @Override
    public String getNullableResult(ResultSet resultSet, int i) throws SQLException {return null;}

    @Override
    public String getNullableResult(CallableStatement callableStatement, int i) throws SQLException {return null;}

}

2)最简略的状况下下面定义曾经能够了,咱们还能够本人指定处理器解决的数据库字段类型,通过 @MappedJdbcTypes 注解来指定,比方我这里要解决的是表中的 varchar 类型数据,如果不指定则默认取 key 为 null 的对应 jdbc 类型处理器

@MappedJdbcTypes(value = JdbcType.VARCHAR)

3)另外还能够通过 @MappedTypes 注解来指定解决对应的 java 类型,如果没指定,则默认取 BaseTypeHandler 中对应的泛型类的理论类型

@MappedTypes(value = String.class)

4)最初须要在配置中指定类型处理器的门路

mybatis.type-handlers-package=com.example.mybatisanalyze.typehandler

实现原理

注册流程

自定义一个类型处理器如此简略,它的实现原理也不难,咱们来看下是如何实现的。这里先看一个十分重要的类 TypeHandlerRegistry,该类就是类型处理器治理类,所有的类型处理器都在这外面保护着

能够看到在构造函数里就会注册内置的类型处理器。在咱们配置了对应的类型处理器所在包门路之后,mybatis-spring 或者 mybatis 就会调用对应的注册接口进行注册

这外面的逻辑比较简单,就不细说,晓得一点就能够:外面保护的 map 构造是 <javatype, map<jdbctype, typehandler>>,也就是先依据 java 类型取到对应的汇合,再通过表字段类型取到对应的处理器。

解决流程

对于解决流程,要调试的话,要害看一个类:BaseTypeHandler。这里用到了模板模式,所有的处理器都要先通过基类的模板解决,再调子类的定制化逻辑。它继承的是 TypeHandler

从对应的接口名称中咱们也能看进去,setParameter 是用来将 java 类型转换为表字段类型的,其余的是用来讲表字段类型转换为 java 类型的。咱们平时在执行逻辑的时候用的是 DefaultSqlSession,以selectOne 函数来举例看下是在哪里做类型转换解决的。从 org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object) 始终跟进去

这里默认用的缓存执行器,也就是 CachingExecutor。持续跟进去

缓存不存在的话,会应用 BaseExecutor 来执行查问,两头的链路不多介绍了,间接看 org.apache.ibatis.executor.SimpleExecutor#prepareStatement

在这里做参数的类型解决,跟进到 org.apache.ibatis.scripting.defaults.DefaultParameterHandler#setParameters

能够看到这里就是遍历参数,依据参数类型获取对应的类型处理器一一解决。
再来看下对于数据库查回的后果集是如何做解决的,看下如下逻辑
org.apache.ibatis.executor.statement.PreparedStatementHandler#query

这里会调用对应的连接池执行数据库操作,而后进行后果解决。而后间接跟到 org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getRowValue(org.apache.ibatis.executor.resultset.ResultSetWrapper, org.apache.ibatis.mapping.ResultMap)

这里开始获取对应的行数据,我画红框的中央就是表字段和 Java 类型字段映射解决逻辑,跟进去看下

这里又呈现了 TypeHandler,这里就是具体的类型处理器对后果进行解决的逻辑。

总结

本文具体介绍了 mybatis 的类型处理器,看完你会发现原来类型处理器实现也是很简略的。

正文完
 0