一、简介

使用Mybatis最大的特性就是sql需要自己写,而写sql难免需要传递多个参数。相信大家在使用Mybatis的时候都遇到过 "Parameter 'array' not found. Available parameters are [xsids, param1]" 类似这样的错误,本文将总结一下Mybatis复杂参数传参取参的方式。

二、不使用@Param注解

【a】传递List<xx>类型参数:当不使用@Param注解时,在xml中通过foreach循环,此时必须指定collection=”list”或者collection=”collection”才能取出参数;
(1). Mapper.java:

/*** mybatis传复杂参数(不使用@Param("xxx")指定参数名称)*/List<Map<String, Object>> getStudentsByListNoParamName(List<Integer> pkids);

(2). Mapper.xml:

<!--List<Map<String, Object>> getStudentsByListNoParamName(List<Integer> pkids);注意: 因为没有通过@Param指定参数名称,mybatis规定如果是Collection并且没有指定参数名称,那么collection="list"必须为list或collection否则报错:Parameter 'xxx' not found. Available parameters are [collection, list]--><select id="getStudentsByListNoParamName" resultType="map" parameterType="list">select * from tbl_student twhere 1 = 1and t.s_id in<foreach collection="collection" open="(" close=")" separator="," index="index" item="pkid">#{pkid}</foreach></select>

或者:

<!--List<Map<String, Object>> getStudentsByListNoParamName(List<Integer> pkids);注意: 因为没有通过@Param指定参数名称,mybatis规定如果是Collection并且没有指定参数名称,那么collection="list"必须为list或collection否则报错:Parameter 'xxx' not found. Available parameters are [collection, list]--><select id="getStudentsByListNoParamName" resultType="map" parameterType="list">select * from tbl_student twhere 1 = 1and t.s_id in<foreach collection="list" open="(" close=")" separator="," index="index" item="pkid">#{pkid}</foreach></select>

(3). 单元测试代码:

    @Testpublic void testNoParams() {List<Integer> pkids = new ArrayList<>();pkids.add(1);pkids.add(2);List<Map<String, Object>> students1 = studentMapper.getStudentsByListNoParamName(pkids);for (Map<String, Object> map : students1) {System.out.println(map);}}

(4).运行结果:

如果xml写错为下面,则会报错:

   <select id="getStudentsByListNoParamName" resultType="map" parameterType="list">select * from tbl_student twhere 1 = 1and t.s_id in<foreach collection="xsids" open="(" close=")" separator="," index="index" item="pkid">#{pkid}</foreach></select>

【b】传递Array数组类型参数:当不使用@Param注解时,在xml中通过foreach循环,此时必须指定collection=”array”才能取出参数;
(1). Mapper.java:

List<Map<String, Object>> getStudentsByArrayNoParamName(Integer[] pkids);

(2). Mapper.xml:

<!--List<Map<String, Object>> getStudentsByArrayNoParamName(Integer[] pkids);注意: 因为没有通过@Param指定参数名称,mybatis规定如果是Array数组类型并且没有指定参数名称,那么collection="array"必须为array否则报错:假如我们指定collection="array1",那么报错如下: Parameter 'array1' not found. Available parameters are [array]--><select id="getStudentsByArrayNoParamName" resultType="map">select * from tbl_student twhere 1 = 1and t.s_id in<foreach collection="array" open="(" close=")" separator="," index="index" item="pkid">#{pkid}</foreach></select>

(3).单元测试代码:

    @Testpublic void testNoParams() {List<Map<String, Object>> students2 = studentMapper.getStudentsByArrayNoParamName(new Integer[]{1, 2, 3});for (Map<String, Object> map : students2) {System.out.println(map);}}

(4). 运行结果:

如果xml文件错写成,则会报错。

<select id="getStudentsByArrayNoParamName" resultType="map">select * from tbl_student twhere 1 = 1and t.s_id in<foreach collection="array12" open="(" close=")" separator="," index="index" item="pkid">#{pkid}</foreach></select>

【c】传递Map类型参数:当不使用@Param注解时,在xml文件可以通过#{map的key}取出参数值;
(1). Mapper.java:

 List<Map<String, Object>> getStudentsByMapNoParamName(Map<String, Object> param);

(2). Mapper.xml:

<!--List<Map<String, Object>> getStudentsByMapNoParamName(Map<String, Object> param);注意: 因为没有通过@Param指定参数名称,mybatis规定如果是map类型并且没有指定参数名称,那么在xml中取值的时候:对于普通属性:对应map.put('aaa',bbb) map中的key键对于集合类型属性:也是对应map.put('aaa',bbb) map中的key键对于这个示例,如下:paramMap.put("sname", "zhangsan2");  取值方式  ->  #{sname}paramMap.put("pkids", pkids2);       取值方式  -> collection="pkids"--><select id="getStudentsByMapNoParamName" parameterType="map" resultType="map">select * from tbl_student twhere 1 = 1<if test="sname!=null and sname!=''">and t.s_name = #{sname}</if><if test="pkids != null and pkids.size() > 0">and t.s_id in<foreach collection="pkids" open="(" close=")" separator="," index="index" item="pkid">#{pkid}</foreach></if></select>

(3).单元测试代码:

 @Testpublic void testNoParams() {Map<String, Object> paramMap = new HashMap<>();paramMap.put("sname", "zhangsan2");List<Integer> pkids2 = new ArrayList<>();pkids2.add(1);pkids2.add(2);paramMap.put("pkids", pkids2);List<Map<String, Object>> students3 = studentMapper.getStudentsByMapNoParamName(paramMap);for (Map<String, Object> map : students3) {System.out.println(map);}}

(4). 运行结果:

三、使用@Param注解

【a】传递List<xx>类型参数:假如指定了参数名称为xsids,那么取值方式:collection="xsids", 此时默认的collection、list会失效;
(1).Mapper.java:

/*** mybatis传复杂参数(使用@Param("xxx")指定参数名称)*/List<Map<String, Object>> getStudentsByListWithParamName(@Param("xsids") List<Integer> pkids);

(2).Mapper.xml:

  <!--List<Map<String, Object>> getStudentsByListWithParamName(@Param("xsids") List<Integer> pkids);因为我们指定了参数名称为xsids,所以取值方式:collection="xsids", 此时默认的collection、list会失效如果我们使用collection="list", 会报错:Parameter 'list' not found. Available parameters are [xsids, param1]--><select id="getStudentsByListWithParamName" resultType="map" parameterType="list">select * from tbl_student twhere 1 = 1and t.s_id in<foreach collection="xsids" open="(" close=")" separator="," index="index" item="xsid">#{xsid}</foreach></select>

(3).单元测试代码:

    @Testpublic void testWithParams() {List<Integer> pkids = new ArrayList<>();pkids.add(1);pkids.add(2);List<Map<String, Object>> students1 = studentMapper.getStudentsByListWithParamName(pkids);for (Map<String, Object> map : students1) {System.out.println(map);}}

(4).运行结果:

如果xml中collection不是“xsid”,那么会报错

<select id="getStudentsByListWithParamName" resultType="map" parameterType="list">select * from tbl_student twhere 1 = 1and t.s_id in<foreach collection="list" open="(" close=")" separator="," index="index" item="xsid">#{xsid}</foreach></select>

【b】传递Array类型参数:假如我们指定了参数名称为xsids,那么取值方式:collection="xsids",此时默认的array会失效;

(1).Mapper.java:

 List<Map<String, Object>> getStudentsByArrayWithParamName(@Param("xsids") Integer[] pkids);

(2).Mapper.xml:

    <!--List<Map<String, Object>> getStudentsByArrayWithParamName(@Param("xsids") Integer[] pkids);因为我们指定了参数名称为xsids,所以取值方式:collection="xsids",此时默认的array会失效.如果我们使用collection="array", 会报错:Parameter 'array' not found. Available parameters are [xsids, param1]--><select id="getStudentsByArrayWithParamName" resultType="map">select * from tbl_student twhere 1 = 1and t.s_id in<foreach collection="xsids" open="(" close=")" separator="," index="index" item="pkid">#{pkid}</foreach></select>

(3).单元测试代码:

@Testpublic void testWithParams() {List<Map<String, Object>> students2 = studentMapper.getStudentsByArrayWithParamName(new Integer[]{1, 2, 3});for (Map<String, Object> map : students2) {System.out.println(map);}}

(4).运行结果:

如果xml中的collection不是@Param指定的名字的话,同样会报错:

<select id="getStudentsByArrayWithParamName" resultType="map">select * from tbl_student twhere 1 = 1and t.s_id in<foreach collection="xsids123" open="(" close=")" separator="," index="index" item="pkid">#{pkid}</foreach></select>

【c】传递Map类型参数:假如我们使用@Param("paramMap")指定了参数名称为paramMap,那么我们在xml中取值的时候,就需要通过paramMap.xxx,xxx就是对应map中的键;

(1).Mapper.java:

 List<Map<String, Object>> getStudentsByMapWithParamName(@Param("paramMap") Map<String, Object> param);

(2).Mapper.xml:

<!--List<Map<String, Object>> getStudentsByMapWithParamName(@Param("paramMap") Map<String, Object> param);由于我们使用@Param("paramMap")指定了参数名称为paramMap,所以我们在xml中取值的时候,就需要通过paramMap.xxx,xxx就是对应map中的键,如下paramMap.put("sname", "zhangsan2");  取值方式 -> #{paramMap.sname}paramMap.put("pkids", pkids2);       取值方式 -> collection="paramMap.pkids"--><select id="getStudentsByMapWithParamName" parameterType="java.util.Map" resultType="map">select * from tbl_student twhere 1 = 1<if test="paramMap.sname!=null and paramMap.sname!=''">and t.s_name = #{paramMap.sname}</if><if test="paramMap.pkids != null and paramMap.pkids.size() > 0">and t.s_id in<foreach collection="paramMap.pkids" open="(" close=")" separator="," index="index" item="pkid">#{pkid}</foreach></if></select>

(3).单元测试代码:

@Testpublic void testWithParams() {Map<String, Object> paramMap = new HashMap<>();paramMap.put("sname", "zhangsan2");List<Integer> pkids2 = new ArrayList<>();pkids2.add(1);pkids2.add(2);paramMap.put("pkids", pkids2);List<Map<String, Object>> students3 = studentMapper.getStudentsByMapWithParamName(paramMap);for (Map<String, Object> map : students3) {System.out.println(map);}}

(4).运行结果:

注意,取出参数的时候需要与Map中的key值对应上,否则取不出参数值。

四、mybatis参数封装成map源码解析

  • 下面通过查看mybatis源码了解一下里面是怎么封装参数的,同时可以加深我们对传递参数和取出参数的理解。Mybatis中参数解析过程主要是在这个类 -> ParamNameResolver.java: 下面对源码做了一些注释说明,大家也可以debug一步一步查看其中怎么封装参数的。
    
    // 假设args=[2,学生2],names={0=sid,1=sname}public Object getNamedParams(Object[] args) {int paramCount = this.names.size();//参数不为空时,封装成mapif (args != null && paramCount != 0) {//如果没有@Param注解并且参数个数只有一个,直接返回args[0]if (!this.hasParamAnnotation && paramCount == 1) {return args[(Integer)this.names.firstKey()];} else {Map<String, Object> param = new ParamMap();int i = 0;//遍历names: {0=sid,1=sname}for(Iterator var5 = this.names.entrySet().iterator(); var5.hasNext(); ++i) {Entry<Integer, String> entry = (Entry)var5.next();//names集合的value作为key;//names集合的key作为取值的参考args[0]//params: sid=args[0]=2  sname=args[1]=学生2param.put(entry.getValue(), args[(Integer)entry.getKey()]);String genericParamName = "param" + String.valueOf(i + 1);//注意从1开始, param1...paramN//params: param1=2  param2=学生2if (!this.names.containsValue(genericParamName)) {param.put(genericParamName, args[(Integer)entry.getKey()]);}}return param;}} else {//参数为空的时候直接return nullreturn null;}}

五、总结

  • 方法不加@param注解时,并且只有一个参数的时候:

【a】String类型等,xml中可以通过#{任意值}都可以取出参数值;
【b】Entity对象类型:xml中可以通过#{实体对象中的属性名称}取出参数值;
【c】Map 类型:xml文件可以通过#{map中的键key}可以取出参数值;
【d】List 类型:xml中必须要写collection=”list”或者 collection=”collection”才能够取出参数值;
【e】Array数组类型:xml中必须要写collection=”array”才能够取出参数值;

  • 方法加@param注解时,并且只有一个参数的时候:

【a】String类型等:如@param(value="name") ,xml中可以使用#{name}或者#{param1}取出参数值;
【b】对象Entity类型: 如@param(value="student"),xml可以通过#{student.对象属性}取值,或者#{param1.对象属性}取出参数值;
【c】Map 类型:如@param(value="paramsMap"),xml可以通过#{paramsMap.map的key}取值,或者#{param1.map的key}取出参数值;
【d】List集合类型:如@param(value="ids"),xml中可以通过 collection=“ids”或者collection=”param1”取出参数值;
【e】Array类型:如@param(value="ids"),此时要写collection=“ids”或者collection=”param1”取出参数值;

  • 当有多个参数的时候,如果没有指定@Param,那么可以使用#{param1},#{param2}…#{paramN}取出 或者 使用#{0},#{1}…#{N}取出,否则会报参数找不到异常;如果指定了@Param(value="xxx"),那么取参数的时候 可以使用@Param中指定的名称#{xxx}取出 或者 使用#{param1},#{param2}…#{paramN}取出。

Mybatis复杂参数传参取参方式总结相关推荐

  1. 8、SpringBoot+Mybatis整合------参数取值方式

    前言: 我们知道,在mybatis中,参数取值方式有两种: #{ } 和 ${ } 下面,我们来探讨下#{ }与${ }不同. 一.#{ } 例: select * from student wher ...

  2. Vue路由传参三种方式

    Vue路由传参三种方式 params传参 路由属性配置传参 query传参 一.params传参 this.$router.push({ name:"admin", //这里的pa ...

  3. vue路由传参和取参,四种方法,包会

    路由传参两种形式 后续会继续跟新.耐心等待 传参后续会继续更新 路由取参有几种方式? 你猜 在这里$route:获取路由 获取?号传参的参数(对象) this.$route.params 获取路径传参 ...

  4. mybatis java传参_[Java教程]Mybatis批量和传参

    [Java教程]Mybatis批量和传参 0 2014-07-31 04:00:12 MyBatis中批量插入 方法一: resultType="java.lang.String" ...

  5. 数组作为函数的参数传参时,数组名会退化为指针

    1.数组作为函数的参数传参时,数组名会退化为指针 数组作为函数的参数传参时,数组名会退化为指针,数值传参时,需要把数值的长度一起传过去,另外,sizeof()运算符包含字符串的哨兵'/0',而strl ...

  6. shell脚本中编写SQL中 以传参(${accdate})的方式 动态:求 前12个月的日期和求 前一周(7天的日期)

    shell脚本中 编写SQL中 以传参(${accdate})的方式 动态 求 前12个月的日期 CAST(CAST(DATE_FORMAT(DATE_SUB(from_unixtime(unix_t ...

  7. python get请求 url传参_用Python-get方法向页面发起请求,参数传不进去是怎么回事...

    源自:4-1 接口测试工具-python-get接口实战 用Python-get方法向页面发起请求,参数传不进去是怎么回事 #-*-coding:utf-8-*- import urllib impo ...

  8. mybatis绑定参数 sql调用参数、关联查询各种方式(B站雷丰阳的视频笔记切图、为了复习用。)

    想看视频的请跳转 https://www.bilibili.com/video/BV1d4411g7tv mybatis会把传参封装成一个map,key是递增的数字 #{}和${}的区别 #{}属于预 ...

  9. Lyndon的量化修炼之路——浅谈趋势指标取参方法

    //期市妖风大,小心被刮飞.本文不构成任何实质性建议,也不对任何依此进行的交易结果负责 `` 目前市场多许多投资者仍然依托趋势指标作为交易参考,其中,指标计算过程中给定的参数对交易结果具有相当大的影响 ...

  10. 解密四参七参工程坐标系,并使用图新地球完成四参七参计算,实现不同投影坐标参数数据融合

    1序:什么情况下会涉及到工程坐标系,涉及到四参七参? 1.1工程坐标系的相关概念 工程坐标系(engineering coordinate system)是2012年公布的地理信息系统名词 在测区内任 ...

最新文章

  1. jquery 的3D Carousel插件参数说明
  2. Swift 中使用 SQLite——新增数据
  3. wp-login.php 404页面,wordpress隐藏后台登陆界面,自动跳转首页或404
  4. airflow 部署
  5. `object.__init__`
  6. mysql 不同的记录_Mysql通过一个限制条件,查出多条不同的记录
  7. Delphi Sockets.pas单元中TIpSocket的Bug
  8. vs2015配置boost c++
  9. backupexec linux oracle,自动恢复 - 详解通过Backup Exec来实施Oracle灾难恢复_数据库技术_Linux公社-Linux系统门户网站...
  10. Go 处理PCAP文件
  11. matlab排序函数 下标,Matlab自带排序函数sort用法
  12. 测试管理005:面对用户反馈的缺陷,测试人员能做些什么?
  13. 薄膜检测有哪些工艺流程,快来做功课
  14. c语言strstr的使用及模拟实现strstr函数
  15. CSS Sprites(精灵图)
  16. 计算共形几何-代数拓扑
  17. 学人工智能好就业吗?AI职业前景分析
  18. 苹果x付款显示服务器异常,怎么解决App Store未完成付款或AppleID登录失败
  19. 如何应用迅捷CAD编辑器,来绘制一份立体图形。
  20. VTK系列45_图像进行理想低通滤波器处理(频域处理)

热门文章

  1. python 解压缩字符串_在C中压缩字符串,在python中解压缩
  2. XML转换为dataframe
  3. 混编Swift类和Objc类
  4. linux 系统命令启动,Linux开关机及系统进程命令
  5. linux怎么卸载软件 apt,linux安装和卸载软件:sudo apt-get install(remove)
  6. java lambda有必要_深度分析:java8的新特性lambda和stream流,看完你学会了吗?
  7. Neurons and the brains
  8. 一阶线性微分方程的初等积分法例题
  9. 计算机文化基础考试 名词解释,《计算机文化基础》模拟试卷.doc
  10. 西门子S7系列中间人攻击:流量劫持和转发(一)