Mybatis学习系列(三)动态SQL
在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的更多相关文章
- MyBatis学习系列三——结合Spring
目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring MyBatis在项目中应用一般都要结合Spring,这一章主要把MyBat ...
- MyBatis:学习笔记(4)——动态SQL
MyBatis:学习笔记(4)——动态SQL
- MyBatis学习总结_11_MyBatis动态Sql语句
MyBatis中对数据库的操作,有时要带一些条件,因此动态SQL语句非常有必要,下面就主要来讲讲几个常用的动态SQL语句的语法 MyBatis中用于实现动态SQL的元素主要有: if choose(w ...
- MyBatis学习06(动态SQL和缓存)
10.动态SQL 10.1 什么是动态SQL 动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句. 官网描述: MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或 ...
- Mybatis学习笔记(六) —— 动态sql
通过mybatis提供的各种标签方法实现动态拼接sql. 需求:根据性别和名字查询用户 查询sql: SELECT id, username, birthday, sex, address FROM ...
- Mybatis学习笔记之---动态sql中标签的使用
动态Sql语句中标签的使用 (一)常用标签 1.<if> if标签通常用于WHERE语句中,通过判断参数值来决定是否使用某个查询条件, 他也经常用于UPDATE语句中判断是否更新某一个字段 ...
- mybatis学习记录五——动态sql
8 动态sql 8.1 什么是动态sql mybatis核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接.组装. 8.2 需求 用户信息综合查询列表 ...
- 【MyBatis学习07】动态sql
1. 动态sql 动态sql是mybatis中的一个核心,什么是动态sql?动态sql即对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接.组装.就拿上一篇博文中对用户的综合查询一例来 ...
- mybatis学习系列三(部分)
1 forearch_oracle下批量保存(47) oracle批量插入 不支持values(),(),()方式 1.多个insert放在begin-end里面 begin insert into ...
- 1.3(Mybatis学习笔记)动态SQL
一.<if> 使用<if>可以根据具体情况来拼接SQL语句,使其更加灵活更加适应我们的需求. <if>的标签体中是需要拼接的语句,满足条件才会将其进行拼接. < ...
随机推荐
- MySQL配置和启动
1.首先下载MySQl安装包,解压安装包 打开mysql下面的bin文件夹,双击如图标记的 .exe运行 2.配置Mysql (1)运行程序后点击 next (2)这里有精确配置和标准配置,根据情况 ...
- Java的内存--内存溢出vs内存泄露(2)
系统上线后,经常会出现内存不足等错误out of memory,很是头疼,决定要一探究竟 内存溢出 1. 定义及原因 内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使 ...
- C++练习--创建Boat类和Car类(含友元)
/* 定义Boat与Car两个类,二者都有weight属性, 定义二者的一个友元函数totalWeight()为外部函数, 计算二者的重量和. */ #include<iostream> ...
- Maria-DB
mysql客户端可用选项: -A, --no-auto-rehash 禁止补全 -u, --user= 用户名,默认为root -h, --host= 服务器主机,默认为localhost -p, - ...
- Django---URL、Views
1.Django URL(路由系统) URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表:你就是以这种方式告诉Djang ...
- Java源码解析——集合框架(三)——Vector
Vector源码解析 首先说一下Vector和ArrayList的区别: (1) Vector的所有方法都是有synchronized关键字的,即每一个方法都是同步的,所以在使用起来效率会非常低,但是 ...
- Java学习笔记一:三步搭建Java开发环境
Java开发环境搭建 一:安装JDK: 1.下载地址:http://www.oracle.com/technetwork/java/javase/downloads 非常显眼的下载界面 2.点击下载后 ...
- ESP32 LyraT音频开发板试玩(二):播放音乐
我是卓波,很高兴你来看我的博客. 系列文章: ESP32 LyraT音频开发板试玩(一):搭建开发环境 ESP32 LyraT音频开发板试玩(二):播放音乐 本文延续上一篇博客 将D:\msys32\ ...
- linux网络服务实验
1.设置window IP地址为192.168.3.XX,掩码24位. 2.设置Linux IP地址为192.168.3.YY,掩码24位.window与Linux互相ping通. 3.在linux中 ...
- 001---Linux系统的启动过程
Linux系统的启动过程 按下电源 开机自检(BIOS):检查cpu.内存.硬盘是否有问题,找到启动盘. MBR引导(master boot record):主引导记录,读取存储设备的512bytes ...