一、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>

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

  1. mybatis源码学习(一) 原生mybatis源码学习

    最近这一周,主要在学习mybatis相关的源码,所以记录一下吧,算是一点学习心得 个人觉得,mybatis的源码,大致可以分为两部分,一是原生的mybatis,二是和spring整合之后的mybati ...

  2. mybatis源码学习:一级缓存和二级缓存分析

    目录 零.一级缓存和二级缓存的流程 一级缓存总结 二级缓存总结 一.缓存接口Cache及其实现类 二.cache标签解析源码 三.CacheKey缓存项的key 四.二级缓存TransactionCa ...

  3. mybatis源码学习:基于动态代理实现查询全过程

    前文传送门: mybatis源码学习:从SqlSessionFactory到代理对象的生成 mybatis源码学习:一级缓存和二级缓存分析 下面这条语句,将会调用代理对象的方法,并执行查询过程,我们一 ...

  4. mybatis源码学习:插件定义+执行流程责任链

    目录 一.自定义插件流程 二.测试插件 三.源码分析 1.inteceptor在Configuration中的注册 2.基于责任链的设计模式 3.基于动态代理的plugin 4.拦截方法的interc ...

  5. Mybatis源码学习第六天(核心流程分析)之Executor分析

    今Executor这个类,Mybatis虽然表面是SqlSession做的增删改查,其实底层统一调用的是Executor这个接口 在这里贴一下Mybatis查询体系结构图 Executor组件分析 E ...

  6. Spring mybatis源码篇章-Mybatis的XML文件加载

    通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-Mybatis主文件加载 前话 前文主要讲解了Mybatis的主文件加载方式,本文则分析不使用主文件加载方式 ...

  7. mybatis源码学习(三)-一级缓存二级缓存

    本文主要是个人学习mybatis缓存的学习笔记,主要有以下几个知识点 1.一级缓存配置信息 2.一级缓存源码学习笔记 3.二级缓存配置信息 4.二级缓存源码 5.一级缓存.二级缓存总结 1.一级缓存配 ...

  8. Mybatis源码学习之parsing包(解析器)(二)

    简述 大家都知道mybatis中,无论是配置文件mybatis-config.xml,还是SQL语句,都是写在XML文件中的,那么mybatis是如何解析这些XML文件呢?这就是本文将要学习的就是,m ...

  9. Mybatis源码学习之整体架构(一)

    简述 关于ORM的定义,我们引用了一下百度百科给出的定义,总体来说ORM就是提供给开发人员API,方便操作关系型数据库的,封装了对数据库操作的过程,同时提供对象与数据之间的映射功能,解放了开发人员对访 ...

  10. Mybatis源码学习第八天(总结)

    源码学习到这里就要结束了; 来总结一下吧 Mybatis的总体架构 这次源码学习我们,学习了重点的模块,在这里我想说一句,源码的学习不是要所有的都学,一行一行的去学,这是错误的,我们只需要学习核心,专 ...

随机推荐

  1. linux技能点三 find grep

    find:      1.   按文件名查找    find . -name "a*.txt"     注意双引号:  2.   按文件大小查找 find .-size [+/-] ...

  2. java服务端集成极光消息推送--详细开发步骤

    1.极光推送账号准备 要使用极光消息推送必须先在官方网站上注册账号,并添加应用. 产品介绍:https://docs.jiguang.cn/jpush/guideline/intro/ 注册开发者账号 ...

  3. js跳出循环的方法区别(break,continue,return)(转载)

    转自:http://blog.csdn.net/fxss5201/article/details/52980138 js编程语法之break语句: break语句会使运行的程序立刻退出包含在最内层的循 ...

  4. python_多线程

    1.多线程的实现与阻塞 import time import threading def fun_yellow(num): for i in range(1,num+1): print('正在拿第:' ...

  5. 微信小程序和APP优劣势大对比

    小程序的优势: 1. 无需下载,随走随关 2. 功能丰富,体验更简便 3. 接口众多,可以进行不断的开发 4. 流量入口大,背靠日活9.6亿的微信 5. 有强大的微信生态环境 小程序对比APP的好处: ...

  6. Git的工作流程

    git的工作流程为: 克隆Git资源作为工作目录 在克隆的资源上添加或者修改文件 如果别人修改了,你可以更新资源 在提交前查看修改 提交修改 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交 ...

  7. 初学Django基础02 ORM操作

    django的ORM操作 之前我们知道了models.py这个文件,这个文件是用来读取数据结构的文件,每次操作数据时都走这个模块 常用字段 AutoField int自增列,必须填入参数 primar ...

  8. Alpha冲刺(8/10)——2019.5.1

    所属课程 软件工程1916|W(福州大学) 作业要求 Alpha冲刺(8/10)--2019.5.1 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪万 ...

  9. 编程小白入门分享一:git的最基本使用

    git简介 引用了网上的一张图,这张图清晰表达git的架构.workspace是工作区,可以用编辑器直接编辑其中的文件:Index/Stage是暂存区,编辑后的文件可以添加到(add)暂存区:Repo ...

  10. 1、Python简介与Python安装

    一.Python简介: Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python的创始人为吉多·范罗苏姆(Guido van Rossum)少数几个不秃头的语言创始 ...