【mybatis源码学习】mybatis的参数处理

一、mybatis的参数处理以及参数取值

1、单个参数

  • mybatis不做任何处理
  • 取值方式:

    ? #{参数名/任意名}

<!-- Employee getEmpById(Integer id);  -->
<select id="getEmpById" resultType="com.mxc.bean.Employee">
    select * from employee where id=#{id}
</select>

2、多个参数

  • mybatis会将多个参数自动封装为一个map

    ? key:param1,…,paramN,也可以是0,…,N-1(即参数索引,N是参数的个数)

    ? value:参数值

  • 取值方式:

    ? #{上述的key}

<!-- Employee getEmpByIdAndLastName(Integer id, String lastName);  -->
<select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee">
    select * from employee where id=#{param1} and last_name=#{param2}
</select>

为多个参数指定明确的key

  • @Param注解可以为参数指定一个明确的key,方便在sql中取参数值
  • 取值方式:

    ? #{@Param注解指定的key}

<!-- Employee getEmpByIdAndLastName(@Param("id")Integer id, @Param("lastName")String lastName);  -->
<select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee">
    select * from employee where id=#{id} and last_name=#{lastName}
</select>

参数多时会封装map,为了取参数值方便,使用@Param来指定封装时使用的key

3、参数是一个POJO

  • 若多个参数刚好是一个POJO中的属性值,可以直接传入一个POJO
  • 取值方式:

    ? #{属性名}

<!-- Employee getEmpByIdAndLastName(Employee emp);  -->
<select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee">
    select * from employee where id=#{id} and last_name=#{lastName}
</select>

4、参数是一个Map

  • 若多个参数不是某一个POJO的属性,可以封装为一个Map
  • 取值方式:

    ? #{Map的key}

<!--
    Employee getEmpByIdAndLastName(Map<String, Object> map);
    map:
        Map<String, Object> map = new HashMap<>();
        map.put("id", 1);
        map.put("lastName", "mxc");
-->
<select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee">
    select * from employee where id=#{id} and last_name=#{lastName}
</select>

小试牛刀

Employee getEmp(@Param("id")Integer id,String lastName);
// 取值:id=>#{id/param1},lastName=>#{param2}

Employee getEmp(Integer id,@Param("e")Employee emp);
// 取值:id=>#{param1},lastName => #{param2.lastName/e.lastName}

#{}与${}的异同
同:

? 可以获取map中的值或者pojo对象属性的值

异:

#{}:是以预编译的形式,将参数设置到sql语句中,可以防止sql注入
${}:取出的值直接拼装在sql语句中,会有安全问题
使用场景

大多情况下,取参数的值使用#{}。在原生JDBC不支持占位符的地方可以使用${}。如按年份分表查询:select * from ${year}_salary;

二、mybatis的参数处理的源码实现

1、 内部数据结构

package com.spring.test.service.mybatis;

import org.apache.ibatis.builder.ParameterExpression;

/**
 *
 */
public class paramHandler {

    public static void main(String[] args) {
        paramsTokenHandler();
    }

    /**
     * 方法名:List<User> queryList(String name, RowBounds rowBounds, int age, @Param("address") String addresss);
     * 参数内部映射:
     * MethodSignature.SortedMap<Integer, String> params
     *      参数列表的下标->参数名字(如果是@Param,则显示的是注解的value,否则为参数列表当前的除了RowBounds,ResultHandler以外的参数排名次数)
     *      0->0
     *      2->1
     *      3->address
     *
     * MethodSignature.convertArgsToSqlCommandParam(Object[] args)  返回:ParamMap
     *
     *     ParamMap内部存储如下:
     *     参数名字->参数下标
     *     0->name的值
     *     1->age的值
     *     address->addresss的值
     *
     *     param1->name的值
     *     param2->age的值
     *     param3->addresss的值
     *
     */
    public static void paramsToParamMap(){

    }

    /**
     * 例子:#{checkedTime,jdbcType=BIGINT,typeHandler=com.meituan.payment.fundsgateway.core.model.handler.DateForLongTypeHandler}
     */
    public static void paramsTokenHandler(){
        String token="checkedTime,jdbcType=BIGINT,typeHandler=com.meituan.payment.fundsgateway.core.model.handler.DateForLongTypeHandler";
        ParameterExpression parameterExpression=new ParameterExpression(token);
        String name=parameterExpression.get("property");
        System.out.println(name);
        String jdbcType=parameterExpression.get("jdbcType");
        System.out.println(jdbcType);
        String typeHandler=parameterExpression.get("typeHandler");
        System.out.println(typeHandler);
    }
}

2、涉及到的特殊数据结构和算法

org.apache.ibatis.scripting.defaults.DefaultParameterHandler

=>通过sql解析的ParameterMapping循环遍历,从参数列表中获取指定的值,设置至sql语句中的?占位符。

org.apache.ibatis.reflection.MetaObject

=>将方法的参数列表包装成MetaObject,提供统一获取参数值的方法

org.apache.ibatis.reflection.property.PropertyTokenizer

=>根据sql语句占位符#{propertyName}中的propertyName去MetaObject中获取sql语句中的?的值。

org.apache.ibatis.builder.SqlSourceBuilder

org.apache.ibatis.builder.ParameterMappingTokenHandler

org.apache.ibatis.parsing.GenericTokenParser

org.apache.ibatis.builder.ParameterExpression

=>将sql语句中#{}替换成?,并解析出List<ParameterMapping>

原文地址:https://www.cnblogs.com/shangxiaofei/p/11442966.html

时间: 2024-08-01 11:36:27

【mybatis源码学习】mybatis的参数处理的相关文章

Mybatis源码学习记录

一.对源码先上一个结构图: 源代码主要在org.apache.ibatis目录下,18个包,其中在应用中主要的包有:builder.session.cache.type.transaction.datasource.jdbc.mapping,提供支撑服务的包有annotation.binding.io.logging.plugin.reflection.scripting.exception.executor.parsing 二.从使用入手 MyBatis使用的三板斧是SqlSessionFac

mybatis专题(三)-----mybatis源码学习

源码分析概述 源码包分析 下载地址 MyBatis 源码下载地址:https://github.com/mybatis/mybatis-3 导入过程 1. 下载MyBatis的源码 2. 检查maven的版本,必须是3.25以上,建议使用maven的最新版本 3. mybatis的工程是maven工程,在开发工具中导入,工程必须使用jdk1.8以上版本: 4. 把mybatis源码的pom文件中true,全部改为false,或者直接删除这行: 5. 在工程目录下执行 mvn clean inst

MyBatis源码分析-MyBatis初始化流程

MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录.如何新建MyBatis源码工程请点击MyBatis源码分析-IDEA新建MyBatis源码工程. MyBatis初始化的过程也就是创建Configura

mybatis源码学习: 编译的方法

mybatis3用了一段时间,抽出时间来研究一下.具体用法参考官方文档就行,源码在这里.mybatis相对而言,规模较小,可以从中学习如何编写高质量的java项目. mybatis3使用maven管理.方法很简单. 1,mybatis3项目依赖父项目,所以先clone这个项目,然后mvn install 就可以了.就会安装到本地仓库. 2.再mvn install  mybatis-3对应的项目就成功了

Mybatis 源码学习系列

前言 很久以前,我们学习了Java,从一个控制台的 Hello world .开始,我们进入了面向对象的世界. 然后由学习了SQL语言,可以写出SQL语句来将尘封在硬盘之下的数据库数据,展现出来. 后来我们使用JDBC 来操作数据库,进行各种增删改查.然而,我们对于原生的JDBC并不满意,写起来很不爽-- 于是,我们使用了Mybatis,写了一个又一个的mapper,无论需求怎么变动,无论情况怎么复杂多变.对于我们来说只是增加mapper,修改xml中的sql就好了. 从此,一切似乎很简单,水到

mybatis源码学习: 动态代理的应用(慢慢改)

动态代理概述 在学spring的时候知道使用动态代理实现aop,入门的列子:需要计算所有方法的调用时间.可以每个方法开始和结束都获取当前时间咋办呢.类似这样: long current=system.currenttimemillis(); 调用原来的方法 long last=system.currenttimemillis(); 如果每个方法都人工加入实在有点不爽,动态代理出场了.动态代理利用字节码技在原来对应的类的子节码进行重写,添加对应的逻辑. 主流的动态代理实现技术主流如下:JDK 和C

mybatis源码学习(二):SQL执行

从上一篇文章中,我们了解到MapperMethod将SQL的执行交给了sqlsession处理.今天我们继续往下看处理的过程. SqlSession接口除了提供获取Configuration,Mapper的方法之外,主要的作用就是提供增删该查的方法. /** * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License&q

【mybatis源码学习】调试mybatis的第一个程序

[一].基础知识准备 mybatis-config.xml配置文件的结构 MyBatis配置文件中大标签configuration下子标签包括: configuration |--- properties |--- settings |--- typeAliases |--- typeHandlers |--- objectFactory |--- plugins |--- environments |--- |--- environment |--- |--- |--- transaction

mybatis 源码学习(一)配置文件初始化

mybatis是项目中常用到的持久层框架,今天我们学习下mybatis,随便找一个例子可以看到通过读取配置文件建立SqlSessionFactory,然后在build拿到关键的sqlsession,这是我从网上随便找了下例子, 关键的方法在于new SqlSessionFactoryBuilder().build(reader); 可以看到parser.parse() 返回的结果是Configuration ,而mybatis所有的配置文件初始化在这个类里面,这个是很关键的类. 这里可以看到读取