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>的标签体中是需要拼接的语句,满足条件才会将其进行拼接. < ...
随机推荐
- 判断无向图两点间是否存在长度为K的路径
#include <iostream> #include <vector> #define MAXN 5 using namespace std; struct edge { ...
- jquery和vue分别对input输入框手机号码格式化(344)
jQuery function fomatterTel(val, old) {//val: 当前input的值,old: input上次的值 var str = ""; var t ...
- 微信小程序之公共组件写法
我们要实现如下图功能 小程序一个公共的弹出组件,首先我们创建一个pop文件 然后在生成的pop.json文件中将component定义为true { "component": tr ...
- QQ兴趣部落 大批量引流实战技巧
兴趣部落,犹如pc端贴吧,除去盔甲,几乎大同小异. 在文章<QQ运动,新楛的马桶还在香,营销人不应摒弃>中,阿力推推对稍微僻静的平台做过简述,和QQ运动一样,兴趣部落稍显“僻静”,执行到位 ...
- php安装php-redis扩展
下载安装php-redis扩展: 地址:https://github.com/phpredis/phpredis/ $ wget http://pecl.php.net/get/redis-3.1.2 ...
- WordPress4.9 最新版本网站安全漏洞详情与修复
wordpress 目前互联网的市场占有率较高,许多站长以及建站公司都在使用这套开源的博客建站系统来设计网站,wordpress的优化以及html静态化,深受google以及搜索引擎的喜欢,全世界大约 ...
- unity开发c#代码
1.摄像头跟随主角移动,并支持旋转. 开发过程中需要摄像头以一定距离跟随player,同时会进行旋转,属于一种常见的跟随方式. using UnityEngine; using System.Coll ...
- crest value &minimum
public class paixu { public static void main(String[] args) { double temp; double num[]={5.1, 7.12, ...
- Unicode控制字符
Unicode控制字符就是特殊的Unicode字符 控制字符转义代码对照表 Unicode-控制字符 LRM RLM ZWJ ZWNJ LRE LRO RLO PDF NADS ...
- SPFA算法(2) POJ 1511 Invitation Cards
原题: Invitation Cards Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 31230 Accepted: ...