MyBatis ParameterHandler的具体使用

2025-08-30 14:50

本文主要是介绍MyBatis ParameterHandler的具体使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《MyBatisParameterHandler的具体使用》本文主要介绍了MyBatisParameterHandler的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

一、概述

书接上回,StatementHandler参数处理&结果处理,分别委托给ParameterHandler&ResultSetHandler(注意不是ResultHandler)。那么本文介绍一下ParameterHandler

本系列的第二章,我们讲了MyBATis的参数处理,那个参数处理,是把Mapper中各种可能的参数封装为Map,而这个参数处理,是把Map参数,设置到JDBC的Statement中。

二、源码

MyBatis中ParameterHandler只有一个实现DefaultParameterHandler,我们通过源码来解析其工作原理。

1 关键属性

DefaultParameterHandler 的关键属性:

  • MappedStatement:包含SQL元信息;
  • parameterObject:Mapper方法传入的原始参数;
  • BoundSql:包含解析后的 SQL 语句和参数映射列表;
  • TypeHandlerRegistry:类型处理器注册表,用于China编程查找合适的 TypeHandler。
public class DefaultParameterHandler implements ParameterHandler {
    private final MappedStatement mappedStatement;
    private final Object parameterObject;
    private final BoundSql boundSql;
    private final Configuration configuration;
    private final TypeHandlerRegistry typeHandlerRegistry;

    public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
        this.mappedStatement = mappedStatement;
        this.parameterObject = parameterObject;
        this.boundSql = boundSql;
        this.configuration = mappedStatement.getConfiguration();
        this.typeHandlerRegistry = configuration.getTypeHandlehttp://www.chinasem.cnrRegistry();
    }
}

2.setParameters

setParameters 是ParameterHandler的核心方法,负责将参数绑定到 PreparedStatement 中:

@Override
public void setParameters(PreparedStatement ps) {
  ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
  // 获取SQL中的参数映射列表(每个元素对应一个占位符)
  List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
  if (parameterMappings != null) {
    // 遍历每个参数映射,依次绑定到PreparedStatement
    for (int i = 0; i < parameterMappings.size(); i++) {
      ParameterMapping parameterMapping = parameterMappings.get(i);
      // 忽略输出参数(存储过程场景)
      if (parameterMapping.getMode() != ParameterMode.OUT) {
        Object value;
        String propertyName = parameterMapping.getProperty(); // 参数名称(如"id"、"user.name")
        // 获取参数值:从原始参数对象中解析propertyName对应的 value
        if (boundSql.hasAdditionalParameter(propertyName)) {
          // 从附加参数中获取(<foreach>或<bind>标签可以提供额外参数)
          value = boundSql.getAdditionalParameter(propertyName);
        } else if (parameterObject == null) {
          value = null; // 参数为null时直接设为null
        } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
          // 参数本身就是TypeHandler可以处理的类型
          value = parameterObject;
        } else {
          // 参数是复杂对象,通过反射获取propertyName对应的属性值
          MetaObject metaObject = configuration.newMetaObject(parameterObject);
          value = metaObject.getValue(propertyName);
        }
        // 获取参数对应的TypeHandler(负责Java类型→JDBC类型的转换)
        TypeHandler typeHandler = parameterMapping.getTypeHandler();
        JdbcType jdbcType = parameterMapping.getJdbcType();
        if (value == null && jdbcType == null) {
          jdbcType = configuration.getJdbcTypeForNull();
        }
        try {
          // 调用TypeHandler的方法,将value绑定到PreparedStatement的第i+1个占位符
          typeHandler.setParameter(ps, i + 1, value, jdbcType);
        } catch (SQLException e) {
          throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
        }
      }
    }
  }
}

这段代码的执行流程可分为三步:

  1. 解析参数映射列表(ParameterMapping),每个元素对应 SQL 中的一个占位符
  2. 根据参数名称从参数对象中获取参数值(支持复杂对象的属性访问)
  3. 通过 TypeHandler 将参数值转换为 JDBC 类型并绑定到 PreparedStatement

AdditionalParameter这个额外参数是什么?

  1. foreach标签中的item、index都会被解析为额外参数;
  2. binhttp://www.chinasem.cnd标签,也可以提供额外参数,你可以利用bind标签,使用OGNL表达式以外创建一个变量,并将其绑定到当前的上下文。

3.TypeHandler

TypeHandler(类型处理器)负责Java类型与JDBC类型之间的转换,不只是ParameterHandler处理参数需要他,ResultSetHandler处理返回结果时也需要他。

1.TypeHandler接口定义

通过接口定义就可以看出来,TypeHandler负责JAVA类型与JDBC类型互相转换。

public interface TypeHandler<T> {
    void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
    
    T getResult(ResultSChina编程et rs, String columnName) throws SQLException;
    
    T getResult(ResultSet rs, int columnIndex) throws SQLException;
    
    T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}

2. 内置TypeHandler体系

MyBatis 提供了丰富的内置 TypeHandler,这里的例子只是冰山一角,有兴趣可以看下源码,一般情况下,是不需要自己自定义类型转换器的。具体实现这里不深入了,比较简单,模板模式,BaseTypeHandler实现了一些通用逻辑,子类就是JDBC API的各种调用。有兴趣可以直接看源码。

类型分类典型实现类功能说明
基本类型IntegerTypeHandler处理 Integer 与 JDBC INTEGER 转换
字符串类型StringTypeHandler处理 String 与 JDBC VARCHAR 转换
日期类型LocalDateTimeTypeHandler处理 Java 8 日期类型与 JDBC 日期类型转换
枚举类型EnumTypeHandler处理枚举的名称与 JDBC 类型转换
集合 / 数组类型ArrayTypeHandler处理 Java 数组与 JDBC ARRAY 类型转换

4. JdbcTypeForNull 的作用

jdbcTypeForNull是 MyBatis中用于处理null值参数的重要配置,当参数值为 null且未指定具体JDBC 类型时生效。

其主要作用是解决不同数据库对 null 值处理的兼容性问题,某些数据库,对 null 值的类型非常敏感,需要明确指定 JDBC 类型,比如oracle,需要设置为NULL

可以在XML中配置

<configuration>
    <settings>
        <!-- 设置null值默认的JDBC类型 -->
        <setting name="jdbcTypeForNull" value="NULL"/>
    </settings>
</configuration>

三、小结

ParameterHandler是MyBatis处理Statement的参数的核心组件,通过与 TypeHandler协作,实现了Java 类型到JDBC类型的灵活转换,支撑了MyBatis对各种复杂参数场景的处理能javascript力。

到此这篇关于MyBatis ParameterHandler的具体使用的文章就介绍到这了,更多相关MyBatis ParameterHandler内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于MyBatis ParameterHandler的具体使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155880

相关文章

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

Spring 中的切面与事务结合使用完整示例

《Spring中的切面与事务结合使用完整示例》本文给大家介绍Spring中的切面与事务结合使用完整示例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录 一、前置知识:Spring AOP 与 事务的关系 事务本质上就是一个“切面”二、核心组件三、完

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

使用Python实现Word文档的自动化对比方案

《使用Python实现Word文档的自动化对比方案》我们经常需要比较两个Word文档的版本差异,无论是合同修订、论文修改还是代码文档更新,人工比对不仅效率低下,还容易遗漏关键改动,下面通过一个实际案例... 目录引言一、使用python-docx库解析文档结构二、使用difflib进行差异比对三、高级对比方

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

sky-take-out项目中Redis的使用示例详解

《sky-take-out项目中Redis的使用示例详解》SpringCache是Spring的缓存抽象层,通过注解简化缓存管理,支持Redis等提供者,适用于方法结果缓存、更新和删除操作,但无法实现... 目录Spring Cache主要特性核心注解1.@Cacheable2.@CachePut3.@Ca

C#下Newtonsoft.Json的具体使用

《C#下Newtonsoft.Json的具体使用》Newtonsoft.Json是一个非常流行的C#JSON序列化和反序列化库,它可以方便地将C#对象转换为JSON格式,或者将JSON数据解析为C#对... 目录安装 Newtonsoft.json基本用法1. 序列化 C# 对象为 JSON2. 反序列化

RabbitMQ 延时队列插件安装与使用示例详解(基于 Delayed Message Plugin)

《RabbitMQ延时队列插件安装与使用示例详解(基于DelayedMessagePlugin)》本文详解RabbitMQ通过安装rabbitmq_delayed_message_exchan... 目录 一、什么是 RabbitMQ 延时队列? 二、安装前准备✅ RabbitMQ 环境要求 三、安装延时队

Python ORM神器之SQLAlchemy基本使用完全指南

《PythonORM神器之SQLAlchemy基本使用完全指南》SQLAlchemy是Python主流ORM框架,通过对象化方式简化数据库操作,支持多数据库,提供引擎、会话、模型等核心组件,实现事务... 目录一、什么是SQLAlchemy?二、安装SQLAlchemy三、核心概念1. Engine(引擎)

Java Stream 并行流简介、使用与注意事项小结

《JavaStream并行流简介、使用与注意事项小结》Java8并行流基于StreamAPI,利用多核CPU提升计算密集型任务效率,但需注意线程安全、顺序不确定及线程池管理,可通过自定义线程池与C... 目录1. 并行流简介​特点:​2. 并行流的简单使用​示例:并行流的基本使用​3. 配合自定义线程池​示