在mapper配置文件中,有时需要根据查询条件选择不同的SQL语句,或者将一些使用频率高的SQL语句单独配置,在需要使用的地方引用。Mybatis的一个特性:动态SQL,来解决这个问题。

mybatis动态sql语句是基于OGNL表达式的,主要有以下几类:

1. if 语句 (简单的条件判断)

2. choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似

3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀)

4. where (主要是用来简化sql语句中where条件判断的,能智能的处理 and or ,不必担心多余导致语法错误)、

5. set (主要用于更新时)

6. foreach (在实现 mybatis in 语句查询时特别有用)

if标签语句

  if标签用来实现根据条件拼接sql语句,下面示例用来判断参数如果不为null,则拼接sql

示例:

 <select id="ifTest" resultType="com.sl.po.Product">
select * from products where
<if test="ProductName!=null">
name like #{ProductName}
</if>
<if test="description!=null">
and description like CONCAT(CONCAT('%', #{Description, jdbcType=VARCHAR}),'%')
</if>
</select>

当参数ProductName和Description不为null,则正常拼接处sql语句:select * from products where name like ? and description like CONCAT(CONCAT('%', ?),'%')

但是上面的SQL中如果传入的参数ProductName为null,则解析出错误的语句:select * from products where and description like CONCAT(CONCAT('%', ?),'%') ,解决这个问题,需要用到where标签

where标签语句

  当 where 中的条件使用的 if 标签较多时,这样的组合可能会导致错误, “where”标签会自动判断如果它包含的标签中有返回值的话,就在sql中插入一个‘where’,如果where标签最后返回的内容是以 and 或者or 开头的,也会被自动移除掉。

上面的示例用where标签改写后示例如下:

<select id="whereTest" resultType="com.sl.po.Product">
select * from products
<!-- where标签自动移除第一个and-->
<where>
<if test="Name!=null">
and name like #{Name}
<!--name like #{Name}-->
</if>
<if test="description!=null">
and description like #{Description}
</if>
</where>
</select>

set标签语句

  set 标签是用在更新操作的时候,功能和 where 标签元素差不多,主要是在包含的语句前输出一个 set,然后如果包含的语句是以逗号结束的话将会把该逗号忽略,如果 set 标签最终返回的内容为空的话则可能会出错(update table where id=1)

使用set标签示例:

<!-- if + set 实现按条件更新-->
<update id="setTest">
update products
<!-- set标签将移除最后一个“,” -->
<set>
<if test="cityCode!=null">
citycode = #{cityCode} ,
</if>
<if test="Name!=null">
name = #{Name} ,
</if>
<if test="description!=null">
description = #{Description} ,
</if>
</set>
where id =#{id}
</update>

trim标签语句

  trim 元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是 prefix 和 suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是 prefixOverrides 和 suffixOverrides;正因为 trim 有这样的功能,它可以用来实现 where 和 set 的效果。

前面where标签示例,此处使用trim代替:

<!-- if+trim 使用trim代理where-->
<select id="trimwhereTest" resultType="com.sl.po.Product">
select * from products
<!--
<where>
<if test="Name!=null">
and name like #{Name}
<!--name like #{Name}-->
</if>
<if test="description!=null">
and description like #{Description}
</if>
</where>
-->
<!-- 移除首部所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容-->
<trim prefix="WHERE" prefixOverrides="AND |OR">
<if test="Name!=null">
and name like #{Name}
</if>
<if test="description!=null">
and description like #{Description}
</if>
</trim> </select>

前面set标签示例,此处使用trim代替:

<!--if+trim 代替 使用trime代替set  -->
<update id="trimsetTest">
update products
<!--
<set>
<if test="cityCode!=null">
citycode = #{cityCode} ,
</if>
<if test="Name!=null">
name = #{Name} ,
</if>
<if test="description!=null">
description = #{Description}
</if>
</set>
-->
 <!-- 移除尾部所有指定在 suffixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容-->
      <trim prefix="set" suffixOverrides=",">
<if test="cityCode!=null and cityCode!=''">
citycode = #{cityCode} ,
</if>
<if test="Name!=null">
name = #{Name} ,
</if>
<if test="description!=null">
description = #{Description}
</if>
</trim>
where id=#{id}
</update> 

choose (when, otherwise)标签

  choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql,类似于sql server语句(case when then)

示例:

<!-- choose + when + otherwise 只能选择一个作为查询条件 作用类似sql case when then -->
<select id="choosewhenotherwiseTest" resultType="com.sl.po.Product">
select * from products
<where>
<choose>
<when test="name!=null">
and name like #{Name}
</when>
<when test="description!=null">
and description like #{Description}
</when>
<otherwise>
and unitprice > #{UnitPrice}
</otherwise>
</choose>
</where>
</select>

如果name!=null,则解析出sql: select * from product where name like ?

Name==null&& description!=null,则解析出sql: select * from product where description like ?

否则:select * from product where unitprice >?

foreach标签语句

  mybatis提供foreach标签,用来对一个集合进行遍历,通常是用来构建 IN 条件语句,也可用于其他情况下动态拼接sql语句。

foreach标签有以下几个属性collection, item,index,open,separator,close。

1. collection表示需要遍历的集合

2. item 表示每次遍历时生成的对象名

3. index表示在迭代过程中,每次迭代到的位置)

4. open表示开始遍历时要拼接的字符串

5. separator表示在每次遍历时两个对象直接的连接字符串

6. close表示结束遍历时要拼接的字符串

当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

在使用foreach的时候针对不同的参数类型, collection属性值要分为以下3种情况:

1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list

2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array

3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map或者Object。

示例:

<!-- 只有一个List参数时它的参数名为list,即collection="list" ;  如果参数类型时数组object[],则  collection="array" -->
<select id="foreachTest" resultType="com.sl.po.Product">
select * from products
<where>
<if test="list!=null">
<foreach item="id" index="index" collection="list" open="id in(" separator="," close=")">#{id}</foreach>
</if>
</where>
</select>
<!-- 通过pojo传递list, collection值为pojo中对应的属性名-->
<select id="foreachVoTest" resultType="com.sl.po.Product">
select * from products
<where>
<if test="name!=null"> and name like #{name} </if>
<if test="ids!=null">
<foreach item="item" index="index" collection="ids" open="and id in(" separator="," close=")">#{item}</foreach>
</if>
</where>
</select>

测试代码:

//@Test
public void testforeachTest() {
String statement = "com.sl.mapper.ProductMapper.foreachTest";
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3); List<Product> listProduct = session.selectList(statement, list);
for (Product pro : listProduct) {
System.out.println(pro);
} // 关闭会话
session.close();
} //@Test
public void testforeachVoTest() {
String statement = "com.sl.mapper.ProductMapper.foreachVoTest";
ProductVo2 vo2 = new ProductVo2();
vo2.setName("%国际%");
List<Integer> ids = new ArrayList<Integer>();
ids.add(11);
ids.add(12);
ids.add(13);
vo2.setIds(ids); List<Product> listProduct = session.selectList(statement, vo2);
for (Product pro : listProduct) {
System.out.println(pro);
} // 关闭会话
session.close();
}
package com.sl.po;

import java.util.List;

public class ProductVo2 {

    private String name;

    private List<Integer> ids;

    public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public List<Integer> getIds() {
return ids;
} public void setIds(List<Integer> ids) {
this.ids = ids;
} }

Sql片段

  Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的

示例:

<select id="sqlTest" resultType="com.sl.po.Product">
select * from products
<where>
<!-- 引用sql片段 -->
<include refid="sqltemp"/>
<!-- 提取sql片段
<if test="cityCode!=null">
and citycode = #{cityCode}
</if>
<if test="Name!=null">
and name like #{Name}
</if>
<if test="description!=null">
and description like #{Description}
</if>
-->
</where>
</select> <!-- 定义sql片段 :将where条件提取 -->
<sql id="sqltemp">
<if test="cityCode!=null">
and citycode = #{cityCode}
</if>
<if test="Name!=null">
and name like #{Name}
</if>
<if test="description!=null">
and description like #{Description}
</if>
</sql>

Mybatis学习系列(三)动态SQL的更多相关文章

  1. MyBatis学习系列三——结合Spring

    目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring MyBatis在项目中应用一般都要结合Spring,这一章主要把MyBat ...

  2. MyBatis:学习笔记(4)——动态SQL

    MyBatis:学习笔记(4)——动态SQL

  3. MyBatis学习总结_11_MyBatis动态Sql语句

    MyBatis中对数据库的操作,有时要带一些条件,因此动态SQL语句非常有必要,下面就主要来讲讲几个常用的动态SQL语句的语法 MyBatis中用于实现动态SQL的元素主要有: if choose(w ...

  4. MyBatis学习06(动态SQL和缓存)

    10.动态SQL 10.1 什么是动态SQL 动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句. 官网描述: MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或 ...

  5. Mybatis学习笔记(六) —— 动态sql

    通过mybatis提供的各种标签方法实现动态拼接sql. 需求:根据性别和名字查询用户 查询sql: SELECT id, username, birthday, sex, address FROM ...

  6. Mybatis学习笔记之---动态sql中标签的使用

    动态Sql语句中标签的使用 (一)常用标签 1.<if> if标签通常用于WHERE语句中,通过判断参数值来决定是否使用某个查询条件, 他也经常用于UPDATE语句中判断是否更新某一个字段 ...

  7. mybatis学习记录五——动态sql

    8       动态sql 8.1     什么是动态sql mybatis核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接.组装. 8.2     需求 用户信息综合查询列表 ...

  8. 【MyBatis学习07】动态sql

    1. 动态sql 动态sql是mybatis中的一个核心,什么是动态sql?动态sql即对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接.组装.就拿上一篇博文中对用户的综合查询一例来 ...

  9. mybatis学习系列三(部分)

    1 forearch_oracle下批量保存(47) oracle批量插入 不支持values(),(),()方式 1.多个insert放在begin-end里面 begin insert into ...

  10. 1.3(Mybatis学习笔记)动态SQL

    一.<if> 使用<if>可以根据具体情况来拼接SQL语句,使其更加灵活更加适应我们的需求. <if>的标签体中是需要拼接的语句,满足条件才会将其进行拼接. < ...

随机推荐

  1. iOS 直播类APP开发流程解析

    1 . 音视频处理的一般流程: 数据采集→数据编码→数据传输(流媒体服务器) →解码数据→播放显示1.数据采集:摄像机及拾音器收集视频及音频数据,此时得到的为原始数据涉及技术或协议:摄像机:CCD.C ...

  2. c#常用数据库封装再次升级

    c#封装的几类数据库操作: 1.sqilte 2.berkeleydb 3.一般数据库 4.redis 包含其他项目: 1.序列化 2.通信 3.自定义数据库连接池 再次升级内容: 1.新增redis ...

  3. JavaScript运算操作符

    1. "+" (1)数学运算 var a = 1 + 1; console.log(a); //输出值为2 (2)字符串连接 (任何数据类型加字符串都等于 字符串) var ini ...

  4. #leetcode刷题之路5-最长回文子串

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1:输入: "babad"输出: "bab"注意: " ...

  5. 『ACM C++』HDU杭电OJ | 1425 - sort (排序函数的特殊应用)

    今天真的是累哭了,周一课从早八点半一直上到晚九点半,整个人要虚脱的感觉,因为时间不太够鸭所以就回头看看找了一些比较有知识点的题来总结总结分析一下,明天有空了就开始继续打题,嘻嘻嘻. 今日兴趣电影: & ...

  6. 动态规划(一)POJ1163

    动态规划算法是比较实用的算法之一,结合实际问题能更好的熟悉这个算法 下面以POJ1163为例子 1. 首先是题目大意 :在给定的一个数字三角形中找到一条自上而下的路径,路径每一步只能左下或者右下,最后 ...

  7. Linux 服务器之间文件传输

    linux的scp命令: scp就是secure copy的简写,用于在linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器. 有时我们需要获得远程服务器上 ...

  8. SQL:检索数据-基本检索

    检索数据 1.select语句 增删改查四大操作之"查",即检索: 一般包括:what,where:查什么,从哪里选择 2.检索单个列 例:想从products表中检索名为prod ...

  9. Ehcache基于java API实现

    上代码: package com.utils.cacheutils; import com.situopenapi.constant.EhcacheConstants; import com.situ ...

  10. CVE-2017-11882复现-office命令执行

    0x01 前言 11月14日,微软按照惯例发布了11月的安全更新,随后不久,安全公司EMBEDI在官方博客上公开了其向微软提交的编号为CVE-2017-11882的Office远程代码执行漏洞: ht ...