【Mybatis源码分析】类型处理器(TypeHandler)及其注册

news2025/6/18 1:05:41

TypeHandler和TypeHandlerRegistry

  • TypeHandler
  • TypeHandler 源码分析
  • TypeHandler注册,TypeHandlerRegistry源码分析
  • TypeHandler拓展案例
  • 总结

TypeHandler

大伙都知道Mybatis是对JDBC的封装,那Mybatis是如何处理JDBC类型和Java类型之间的转换的呢?

当在预处理语句(PreparedStatement)中设置一个参数时;
当在结果集(ResultSet)中获取一个值时;
当获取(CallableStatement)处理函数时的返回值时;
都会用类型处理器去处理Java类型和JDBC类型之间的转换。Mybatis默认为我们实现了很多TypeHandler,当我们没有配置指定TypeHandler时,Mybatis会根据参数或者返回结果的不同,默认为我们选择合适的TypeHandler处理。

<typeHandlers>
      <!-- 
          当配置package的时候,mybatis会去配置的package扫描TypeHandler
          <package name="com.dy.demo"/>
       -->
      
      <!-- handler属性直接配置我们要指定的TypeHandler -->
      <typeHandler handler=""/>
      
      <!-- javaType 配置java类型,例如String, 如果配上javaType, 那么指定的typeHandler就只作用于指定的类型 -->
      <typeHandler javaType="" handler=""/>
      
      <!-- jdbcType 配置数据库基本数据类型,例如varchar, 如果配上jdbcType, 那么指定的typeHandler就只作用于指定的类型  -->
      <typeHandler jdbcType="" handler=""/>
      
      <!-- 也可两者都配置 -->
      <typeHandler javaType="" jdbcType="" handler=""/>
      
  </typeHandlers>

TypeHandler 源码分析

// 泛型T指代的是要转换的Java类型
public interface TypeHandler<T> {
	// 对应着ps.set??(?索引,插入值)
  void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
  // 对应着rs.get??(columnName)
  T getResult(ResultSet rs, String columnName) throws SQLException;
	// 对应着rs.get??(columnIndex)
  T getResult(ResultSet rs, int columnIndex) throws SQLException;
	// 对应着cs.get??(columnIndex)
  T getResult(CallableStatement cs, int columnIndex) throws SQLException;

}

现在小编拿一个Mybatis中对其实现的IntegerTypeHander进行举例。
首先看看其继承关系

在这里插入图片描述
再看看其实现(实际就是JDBC代码)

public class IntegerTypeHandler extends BaseTypeHandler<Integer> {

  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType)
      throws SQLException {
    ps.setInt(i, parameter);
  }

  @Override
  public Integer getNullableResult(ResultSet rs, String columnName) throws SQLException {
    int result = rs.getInt(columnName);
    return result == 0 && rs.wasNull() ? null : result;
  }

  @Override
  public Integer getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    int result = rs.getInt(columnIndex);
    return result == 0 && rs.wasNull() ? null : result;
  }

  @Override
  public Integer getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    int result = cs.getInt(columnIndex);
    return result == 0 && cs.wasNull() ? null : result;
  }
}

TypeHandler注册,TypeHandlerRegistry源码分析

Mybatis会根据你使用preparedStatement进行预处理,然后插入数据的类型和返回的结果类型会去自动匹配TypeHandler。那它是怎么注册TypeHandler的呢?使用TypeHandlerRegistry这个类。下面是其源码分析。


主要的三个属性
// 通过JDBC类型映射类型处理器
private final Map<JdbcType, TypeHandler<?>> jdbcTypeHandlerMap = new EnumMap<>(JdbcType.class);
// 通过Java类型和JDBC类型映射唯一的类型处理器
// 从这个map可以看出一个Java类型可以对应多个类型处理器,需要啥可以具体写sql时候进行指定
private final Map<Type, Map<JdbcType, TypeHandler<?>>> typeHandlerMap = new ConcurrentHashMap<>();
// 这里有所有进行配置的类型处理器,与其class对象进行映射其引用
private final Map<Class<?>, TypeHandler<?>> allTypeHandlersMap = new HashMap<>();

注册方法

在这里插入图片描述在这里插入图片描述
核心注册方法

在这里插入图片描述
Mybatis自动注册内容

在这里插入图片描述

TypeHandler拓展案例

Mybatis提供了我们很多类型处理器,当然我们也可以根据自己的需要写属于自己的类型处理器然后配置使用。下面拿枚举性别类型进行举例。(数据库表中是拿数字0,1,2 去指示性别的,现在希望数字和其表示的含义我们都需要)

先看看表对应的pojo类

@Data
@NoArgsConstructor
public class Person {
    private Integer id;
    private String name;
    private Integer age;
    private SexEnum sex;
}

下面是需要转换的Java类型(性别枚举类型)

public enum SexEnum {

    UNKNOW(0,"未知"),
    MAN(1,"男"),
    WOMAN(2,"女");

    private Integer value;
    private String name;

    SexEnum(Integer value, String name) {
        this.value = value;
        this.name = name;
    }

    public Integer getValue() {
        return value;
    }

    public String getName() {
        return name;
    }

    public static SexEnum getByValue(Integer value){
        for (SexEnum item : values()){
            if (item.getValue().equals(value)) {
                return item;
            }
        }
        return null;
    }
}

写类型处理器,可以选择继承BaseTypeHandler类,也可以选择去实现TypeHandler接口。如果不想在配置文件中去配置对应的Java类型的话,那就使用@MappedTypes注解进行配置(当然可以配置多个,因为一个处理器可以对应多个Java数据类型嘛,有类似的枚举也可以配置,从而达到复用)。

@MappedTypes(SexEnum.class)
public class SexEnumHandler extends BaseTypeHandler<SexEnum> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, SexEnum parameter, JdbcType jdbcType) throws SQLException {
        ps.setInt(i,parameter.getValue());
        System.out.println("parameter.value:"+parameter.getValue());
    }

    @Override
    public SexEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Object object = rs.getObject(columnName);
        Integer sex = (object!=null && object instanceof Integer)?(Integer) object:null;
        return SexEnum.getByValue(sex);
    }

    @Override
    public SexEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Object object = rs.getObject(columnIndex);
        Integer sex = (object!=null && object instanceof Integer)?(Integer) object:null;
        return SexEnum.getByValue(sex);
    }

    @Override
    public SexEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return null;
    }
}

然后在Mybatis核心配置文件中进行配置。

<typeHandlers>
        <package name="com.ncpowernode.mybatis.handlertype"/>
    </typeHandlers>

测试结果

在这里插入图片描述

总结

  • 类型处理器内部其实就是JDBC代码,预处理插入数据和获取结果集;
  • 可以在核心配置中通过typeHandlers进行对类型处理器的配置;
  • 可以通过继承BaseTypeHandler或去实现TypeHanlder接口去实现对类型处理器的拓展;

参考文献
类型处理器,这个你得会玩
typeHandler解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/411849.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图文在线翻译-文本翻译

随着国际交流不断增加&#xff0c;越来越多的企业需要将产品介绍、宣传文案等相关信息翻译成多种语言&#xff0c;以扩大海外市场。但传统的翻译过程通常比较繁琐&#xff0c;耗费时间和人力成本也相对较高。为此&#xff0c;我们推出了一款批量图文翻译软件&#xff0c;帮助企…

【设计模式之美 设计原则与思想:规范与重构】35 | 实战一(下):手把手带你将ID生成器代码从“能用”重构为“好用”

上一节课中&#xff0c;我们结合 ID 生成器代码讲解了如何发现代码质量问题。虽然 ID 生成器的需求非常简单&#xff0c;代码行数也不多&#xff0c;但看似非常简单的代码&#xff0c;实际上还是有很多优化的空间。综合评价一下的话&#xff0c;小王的代码也只能算是“能用”、…

Apache配置与应用和优化

--------构建虚拟 Web 主机--------虚拟Web主机指的是在同一台服务器中运行多个Web站点&#xff0c;其中每一个站点实际上并不独立占用整个服务器&#xff0c;因此被称为“虚拟”Web 主机。通过虚拟 Web 主机服务可以充分利用服务器的硬件资源&#xff0c;从而大大降低网站构建…

【数据结构与算法】一、数据结构的基本概念

文章目录一、数据结构的基本概念1.1 数据结构的研究内容1.2 数据类型和抽象数据类型1.3 算法和算法分析1.3.1 算法的时间复杂度1.3.2 算法时间效率的比较1.4 知识回顾一、数据结构的基本概念 1.1 数据结构的研究内容 1.2 数据类型和抽象数据类型 抽象数据类型&#xff08;ADT…

初识linux之线程基本概念

目录 一、进程地址空间和页表再理解 二、线程 1.线程的概念 2. 进程与线程 3. 线程的意义 4.线程的优点缺点 4.1 优点 4.2 缺点 4.linux中线程的优缺点 4.1 优点 4.2 缺点 5. linux中线程创建相关接口 5.1 线程创建 6. 通过代码查看进程与线程的关系 6.1 线程库…

【软件设计师11】面向对象设计

面向对象设计 1. 设计原则 单一职责原则&#xff1a;设计目的单一的类 开放-封闭原则&#xff1a;对外扩展开放&#xff0c;对修改关闭 里氏(Liskov)替换原则&#xff1a;子类可以替换父类 依赖倒置原则&#xff1a;要依赖与对象&#xff0c;而不是具体实现&#xff1b;针…

Windows安装配置Anaconda

要进行各类有意思大模型的运行&#xff0c;首选需要解决环境问题。本文介绍了windows 下安装anaconda、conda的配置、以及conda的常用命令。 一、下载安装 注1&#xff1a;不要求提前安装python。 注2&#xff1a;因为后续环境多了&#xff0c;会占用较大硬盘空间&#xff0…

siPOOLs(一款高效、特异性好的RNAi试剂,可有效消除脱靶效应)

对于靶向基因沉默&#xff0c;RNA干扰&#xff08;RNAi)具有易于操作、快速结果、高效率、广泛适用于各种细胞类型的多重优势。其具有瞬转效应和剂量依赖效应&#xff0c;这点与小分子非常相似。然而&#xff0c;目前的siRNA试剂的特异性和基因沉默效率不是很稳定&#xff0c;阻…

VSCODE配置OPENCV编译环境(windows)

参考文章&#xff1a; https://www.cnblogs.com/kensporger/archive/2020/02/19/12320622.html 1. 安装MinGW-64 和 CMake&#xff0c;这两个一定要把环境变量添加到电脑的环境变量中&#xff0c;并且打开cmake-gui&#xff0c;细节见上文链接 2.生成MakeFiles。 ①先从open…

二叉树的遍历(节点个数及层序遍历)

简易树的图形&#xff1a; #include <stdio.h> #include <stdlib.h>//重定义数据类型 typedef char DataType; //创建简易的二叉树结构体 typedef struct BTNode {struct BTNode* left;struct BTNode* right;DataType data; }BTNode; //前序&#xff08;根左右&am…

2023年股票代持行业研究报告

第一章 股票代持概述 1.1 基本概念 股票代持&#xff0c;或称委托持股&#xff0c;是指实际出资人与名义出资人达成以下约定&#xff1a;名义出资人作为名义股东&#xff0c;在股东名册等公司工商登记信息上出现&#xff0c;而实际上由实际出资人出资并享有投资权益。 股票代…

WPF MVVM模式构建项目

什么是MVVM模式&#xff1f; MVVM是Model-View-ViewModel的简写&#xff0c;Model就是模型&#xff0c;View就是视图&#xff0c;ViewModel就是View和Model之间解耦和传递消息的中间层。MVVM采用双向数据绑定&#xff0c;View中数据变化将自动反映到ViewModel上&#xff0c;反之…

【并发编程】异步编程CompletableFuture实战

文章目录1.CompletableFuture简介2.CompletableFuture核心API实战3.CompletableFuture嵌套案例实战4.合并两个CompletableFuture案例实战5.多个CompletableFuture任务组合调度实战1.CompletableFuture简介 在JDK8之前&#xff0c;我们使用的Java多线程变成&#xff0c;主要是 …

Golang GORM入门

一、GORM入门 1.1 什么是ORM&#xff1f; orm是一种术语而不是软件 orm英文全称object relational mapping&#xff0c;就是对象映射关系简单来说类似python这种面向对象的程序来说一切皆对象&#xff0c;但是我们使用的数据库却都是关系型的 为了保证一致的使用习惯&#xff…

NumPy 数组学习手册:1~5

原文&#xff1a;Learning NumPy Array 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 一、NumPy 入门 让我们开始吧。 我们将在不同的操作系统上安装 NumPy 和相关软件&#xff0c;并查看一些使用 NumPy 的简单代码。 正如“序言”所述&#xff0c;SciPy 与 NumPy 密…

开放式蓝牙耳机推荐,推荐几款具有代表性的骨传导耳机

骨传导耳机是一种骨传导技术和音频技术结合的产品&#xff0c;通过声音将振动从骨头传到听觉神经&#xff0c;从而达到听音的效果。相比于传统的入耳式耳机&#xff0c;骨传导耳机佩戴更舒适&#xff0c;不会对耳朵造成损伤。然而市面上有很多不同类型的骨传导耳机&#xff0c;…

机器学习和深度学习在气象中的应用(台风预报只能订正、风速预报订正、LSTM 方法预测 ENSO)

查看原文>>>Python人工智能在气象中的实践技术应用 目录 专题一、Python 和科学计算基础 专题二、机器学习和深度学习基础理论和实操 2.1 机器学习和深度学习基础理论 2.2 sklearn 和pytorch 库 专题三 、气象领域中的机器学习应用实例 3.1 GFS 数值模式的风速…

【玩转RT-Thread】RT-Thread网络框架:BSD网络接口SAL套接字抽象层

文章目录RT-Thread网络框架&#xff1a;BSD网络接口&SAL套接字抽象层基础知识1.TCP与UDP的区别2.TCP编程 服务端配置过程3.TCP编程 客户端配置过程4.UDP编程 客户端配置过程SAL套接字抽象层1.SAL组件主要功能特点&#xff1a;2.SAL网络框架3.工作原理4.多协议接入与接口函数…

“成年人”的数据库,既要又要也要!

欢迎访问 OceanBase 官网获取更多信息&#xff1a;https://www.oceanbase.com/ 3 月 25 日&#xff0c;第一届 OceanBase 开发者大会在北京举行&#xff0c;《明说三人行》访谈栏目创始人兼主持人卢东明、沃趣科技创始人兼 CEO 陈栋、DBAplus 社群联合创始人杨建荣、PostgreSQL…

7.1 基本运算电路(2)

七、集成运放性能指标对运算误差的影响 在上述各电路运算关系的分析中&#xff0c;均认为集成运放为理想运放。而实际上&#xff0c;当利用运放构成运算电路时&#xff0c;由于开环差模增益 AodA_{od}Aod​、差模输入电阻 ridr_{id}rid​ 和共模抑制比 KCMRK_{CMR}KCMR​ 为有…