源码解读Mybatis List列表In查询实现的注意事项

2019-03-13 23:34|来源: 网络

在SQL开发过程中,动态构建In集合条件查询是比较常见的用法,在Mybatis中提供了foreach功能,该功能比较强大,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内。它也允许你指定开放和关闭的字符串,在迭代之间放置分隔符。这个元素是很智能的,它不会偶然地附加多余的分隔符。下面是一个演示示例:

  <select id="findByIdsMap" resultMap="BaseResultMap">
    Select
    <include refid="Base_Column_List" />
     from jria where ID in
     <foreach item="item" index="index" collection="list" 
                    open="(" separator="," close=")">
                   #{item}
            </foreach>
 </select> 

但由于官方文档对这块的使用,描述的比较简短,细节上也被忽略掉了(可能是开源项目文档一贯的问题吧),也使用不少同学在使用中遇到了问题。特别是foreach这个函数中,collection属性做什么用,有什么注意事项。由于文档不全,这块只能通过源代码剖析的方式来分析一下各个属性的相关要求。

collection属性的用途是接收输入的数组或是List接口实现。但对于其名称的要求,Mybatis在实现中还是有点不好理解的,所以需要特别注意这一点。

下面开始分析源代码(笔记使用的是Mybatis 3.0.5版本)

先找到Mybatis执行SQL配置解析的入口

MapperMethod.java类中 public Object execute(Object[] args) 该方法是执行的入口.

针对 in 集合查询,对应用就是  selectForList SelctForMap 方法。

 

但不管调用哪个方法,都会对原来JDK传入的参数 Object[]类型,通过 getParam方法转换成一个Object,那这个方法是做什么的呢?分析源码如下:

 

上图中标红的两处,很惊讶的发现,一个参数与多个参数的处理方式是不同的(后续很多同学遇到的问题,就有一大部分出自这个地方)。如果参数个数大于一个,则会被封装成Map, key值如果使用了Mybatis的 Param注解,则会使用该key值,否则默认统一使用数据序号,从1开始。这个问题先记下,继续分析代码,接下来如果是selectForList操作(其它操作就对应用相应方法),会调用DefaultSqlSession的public List selectList(String statement, Object parameter, RowBounds rowBounds) 方法

又一个发现,见源代码如下:

 

上图标红部分,对参数又做了一次封装,我们看一下代码

 

 

现在有点清楚了,如果参数类型是List,则必须在collecion中指定为list, 如果是数据组,则必须在collection属性中指定为 array.

现在就问题就比较清楚了,如果是一个参数的话,collection的值取决于你的参数类型。

如果是多个值的话,除非使用注解Param指定,否则都是数字开头,所以在collection中指定什么值都是无用的。下图是debug显示结果。

 

针对上面分析的结果,下面给出了一个使用的解决方案,希望对大家对帮助。

在使用这个功能是需要特别注意以下规则:
1. 当查询的参数只有一个时 
  findByIds(List<Long> ids)
 1.a 如果参数的类型是List, 则在使用时,collection属性要必须指定为 list
 <select id="findByIdsMap" resultMap="BaseResultMap">
         Select
         <include refid="Base_Column_List" />
         from jria where ID in
                  <foreach item="item" index="index" collection="list" 
                         open="(" separator="," close=")">
                        #{item}
                </foreach>
  </select> 
 
 findByIds(Long[] ids)
 1.b 如果参数的类型是Array,则在使用时,collection属性要必须指定为 array
  <select id="findByIdsMap" resultMap="BaseResultMap">
                 select
                 <include refid="Base_Column_List" />
          from jria where ID in
                  <foreach item="item" index="index" collection="array" 
                         open="(" separator="," close=")">
                        #{item}
                </foreach>
  </select> 
 
2. 当查询的参数有多个时,例如 findByIds(String name, Long[] ids)
 这种情况需要特别注意,在传参数时,一定要改用Map方式, 这样在collection属性可以指定名称
         下面是一个示例
         Map<String, Object> params = new HashMap<String, Object>(2);
        params.put("name", name);
         params.put("ids", ids);
        mapper.findByIdsMap(params);
 
 <select id="findByIdsMap" resultMap="BaseResultMap">
                 select
                 <include refid="Base_Column_List" />
          from jria where ID in
                  <foreach item="item" index="index" collection="ids" 
                         open="(" separator="," close=")">
                        #{item}
                </foreach>
   </select> 
 
 
完整的示例如下:
例如有一个查询功能,Mapper接口文件定义如下方法:
List<Jria> findByIds(Long... ids);
使用 in 查询的sql拼装方法如下:
 <select id="findbyIds" resultMap="BaseResultMap">
                 select
                 <include refid="Base_Column_List" />
          from jria where ID in
                  <foreach item="item" index="index" collection="array" 
                         open="(" separator="," close=")">
                        #{item}
                </foreach>
  </select> 
 

Good Luck!
Yours Matthew!

转自:http://yingbin920.iteye.com/blog/1892486

相关问答

更多

电梯机房安全操作注意事项

电梯安全乘坐须知 为保证乘客的人身安全和电梯设备的正常,请遵照以下规定正确使用电梯。 一、禁止携带易燃、易爆或带腐蚀性的危险品乘坐电梯。 二、乘坐电梯时请勿在轿厢内左右摇晃。 三、禁止在轿厢内吸烟以免引起火灾。

mybatis源码如何下载

https://github.com/mybatis/mybatis-3/releases 下面有源码下载,源码是个zip压缩文件

mybatis怎么查询一个set集合

一般使用map传值更好,很少使用set Map<String,Object> map = new HashMap<String, Object>(); map.put("questid", questid);这是你传的参数!!! <select id="selectqanswer" resultMap="QuestAnswerMap" > select id,qid,scnid,aoption,acontent,alat,userid, from t_quest_answer where qid= ...

怎么学习mybatis框架的源码

刚刚好我前段时间做了一个基于SpringMVC + Mybatis + Redis + Freemarker(JSP)的权限控制Demo。地址看下面代码:/** * 百度不让输入网址 * 地址为 */String url = "

如何解读Nginx源码

前提: 1、首先nginx是C语言编写的,你必须知识要有C语言的编程基础,否则很痛苦 2、了解web服务器,反向代理的基本知识,以及HTTP协议,TCP/IP协议的基本知识 如果你已经有丰富的经验,或者是大牛,那前面的前提就是废话,可以略过。 看源码准备: 1、找官网,找贡献者的博客去了解NGINX是做什么的,有什么特性,性能,功能,架构等 2、下载源代码,从分析main函数开始,大致了解启动流程,初始化以及一些程序的启动准备 3、建议找到request逻辑,分析下对请求的整个处理流程,不用很细, ...

mysql如何使用like关键字实现模糊查询?有什么注意事项

以下语句调试通过: 1 SELECT * FROM course WHERE name LIKE '%晓%' 运行效果: 注意事项: 使用 like %name% 这样的语句是不会走索引的,相当于全表扫描; 数据量小的时候不会有太大的问题,数据量大了以后性能会下降的很厉害; 建议数据量大了以后使用搜索引擎来代替这种模糊搜索; 实在不行也要在模糊查询前加个能走索引的条件。

网站建设注意事项

1、网站建设时域名的选择 好的域名及用户好记又利于排名,域名尽量要相关,比如我是做网站优化的,我的域名中就应该包括seo这个词,用户好记,也对排名很有利。域名越短越好,便于用户记忆,如果有老域名就不用新域名,老域名更有利于网站排名。 2、网站建设服务器选择 网站建设对服务器的选择,尽量选择稳定的服务器,速度快的服务器,如果服务器两天三天打不开。及伤害百度蜘蛛的心情有伤害用户的体验,说明公司很不正规,对用户的伤害是巨大的。 3、flash大量运用 笔者遇到过一个让笔者做网站优化的单子,全站全是fla ...

人物解读(Character interpretation)

您正在寻找可以转换为相应*正则表达式的通配符 ,请参阅 使用通配符匹配字符串 例如 private static String WildCardToRegular(String value) { return "^" + Regex.Escape(value).Replace("\\?", ".").Replace("\\*", ".*") + "$"; } 然后照常使用正则表达式操作: using System.Text.RegularExpressions; .. ...

C#元组与列表注意事项(C# Tuple versus List Considerations)

那么除了你提到的之外,还有一个相当显着的区别,即一个元组最多只能包含八个元素。 (好吧,你可以通过使最后一个元组参数输入另一个元组来技术性地制造出任意大的元组,但我不禁感到你必须稍微疯狂才能真正做到这一点。) 与像Python这样的语言中的元组不同,C#中的元组不能真正用作通用数据结构。 C#中一个元组最常见的用例之一是从一个函数返回多个值,或者将多个值传递给由于某些原因只能使用一个的函数(例如,当将e.Argument传递给BackgroundWorker )或任何其他值在这种情况下,您无法制作 ...