mybatis基础系列(三)——动态sql
本文是Mybatis基础系列的第三篇文章,点击下面链接可以查看前面的文章:
mybatis基础系列(二)——基础语法、别名、输入映射、输出映射
动态sql
MyBatis 的强大特性之一便是它的动态 SQL。摆脱了JDBC中根据不同条件拼接 SQL 语句的痛苦。动态 SQL可以帮我们解决复杂需求。mybatis 动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach等标签组合成非常灵活的SQL语句。
根据员工编号或者员工姓名查询员工信息,输入的员工编号可能为空。
<select id="queryByEnameOrEempno" parameterType="com.itpsc.request.EmpRequest" resultType="com.itpsc.vo.EmpVo">
SELECT * FROM t_emp WHERE
<if test="emp.ename!=null">
ename=#{emp.ename}
</if>
<if test="emp.empno!=null">
and empno=#{emp.empno}
</if>
</select>
执行结果:
编号为空
==> Preparing: SELECT * FROM t_emp WHERE ename=?
==> Parameters: itpsc(String)
<== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
<== Row: 7100, itpsc, developer, 7902, 1980-01-10, null, 1000.00, 20
<== Total: 1
姓名为空
==> Preparing: SELECT * FROM t_emp WHERE and empno=?
==> Parameters: 7100(Integer)
从执行结果可以看出,上面的if语句只能是在员工姓名不能为空的情况下执行,如果员工姓名为空sql语句就出错了,If+where语句可以解决这个问题。
if+where语句与trim 语句
<select id="queryByEnameOrEempno" parameterType="com.itpsc.request.EmpRequest" resultType="com.itpsc.vo.EmpVo">
SELECT * FROM t_emp
<where>
<if test="emp.ename!=null">
and ename=#{emp.ename}
</if>
<if test="emp.empno!=null">
and empno=#{emp.empno}
</if>
</where>
</select>
执行结果:
姓名为空
==> Preparing: SELECT * FROM t_emp WHERE empno=?
==> Parameters: 7100(Integer)
<== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
<== Row: 7100, itpsc, developer, 7902, 1980-01-10, null, 1000.00, 20
<== Total: 1
编号为空
==> Preparing: SELECT * FROM t_emp WHERE ename=?
==> Parameters: itpsc(String)
<== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
<== Row: 7100, itpsc, developer, 7902, 1980-01-10, null, 1000.00, 20
<== Total: 1
<where>标签中包含的标签中有返回值的话,它就插入一个where关键字,并且where 标签会自动将其后第一个条件的and或者是or给忽略掉。
trim语句可以实现<where>标签类似的功能:
(1)trim标签可以在包含的内容前加上前缀,也可以在其后加上后缀,对应的属性是prefix和suffix;
(2)trim标签可以把包含内容的首部某些内容忽略,也可以把尾部的某些内容忽略,对应的属性是prefixOverrides和suffixOverrides。
<select id="queryByEnameOrEempno" parameterType="com.itpsc.request.EmpRequest" resultType="com.itpsc.vo.EmpVo">
SELECT * FROM t_emp
<trim prefix="where" prefixOverrides="and | or">
<if test="emp.ename!=null">
and ename=#{emp.ename}
</if>
<if test="emp.empno!=null">
and empno=#{emp.empno}
</if>
</trim>
</select>
执行结果:
empno为空
==> Preparing: SELECT * FROM t_emp where ename=?
==> Parameters: itpsc2(String)
<== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
<== Row: 7101, itpsc2, developer, 7902, 1980-01-10, 2000.00, 1000.00, 20
<== Total: 1 ename为空
==> Preparing: SELECT * FROM t_emp where empno=?
==> Parameters: 7100(Integer)
<== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
<== Row: 7100, itpsc1, mannager, 7902, 1980-01-10, null, 1000.00, 20
<== Total: 1 empno、ename都不为空
==> Preparing: SELECT * FROM t_emp where ename=? and empno=?
==> Parameters: itpsc2(String), 7100(Integer)
<== Total: 0
if+set语句与trim语句
条件判断用<where>标签,同理更新操作用<set>标签。
<select id="updateEnameOrJob" parameterType="com.itpsc.request.EmpRequest">
UPDATE t_emp
<set>
<if test="emp.ename!=null">
ename=#{emp.ename}
</if>
<if test="emp.job!=null">
job=#{emp.job}
</if>
</set>
WHERE empno=#{emp.empno}
</select>
运行结果:
job为空
==> Preparing: UPDATE t_emp SET ename=? WHERE empno=?
==> Parameters: hello(String), 7100(Integer)
ename 为空
==> Preparing: UPDATE t_emp SET job=? WHERE empno=?
==> Parameters: itpsc(String), 7100(Integer)
<set>标签中包含的标签中有返回值的话,它就插入一个set关键字。job和ename都不为空则sql错误,那又如何写呢,trim标签可以帮我们能实现。
<select id="updateEnameOrJob" parameterType="com.itpsc.request.EmpRequest">
UPDATE t_emp
<trim prefix="set" suffixOverrides=",">
<if test="emp.ename!=null">
ename=#{emp.ename},
</if>
<if test="emp.job!=null">
job=#{emp.job},
</if>
</trim>
WHERE empno=#{emp.empno}
</select>
运行结果:
==> Preparing: UPDATE t_emp set ename=?, job=? WHERE empno=?
==> Parameters: itpsc(String), mannager(String), 7100(Integer)
choose(when,otherwise) 语句
上的例子中,job和ename都不为空则是一种条件,job为空且ename不为空是一种条件,ename为空且job不为空是一种条件。实际上,我们要只要满足任意一个条件,就可以执行。choose(when,otherwise) 语句可以帮我们解决,类似jstl。
<select id="updateEnameOrJob" parameterType="com.itpsc.request.EmpRequest">
UPDATE t_emp
<set>
<choose>
<when test="emp.ename!=null and emp.job!=null">
ename=#{emp.ename},job=#{emp.job}
</when>
<otherwise>
<if test="emp.ename!=null">
ename=#{emp.ename}
</if>
<if test="emp.job!=null">
job=#{emp.job}
</if>
</otherwise>
</choose>
</set>
WHERE empno=#{emp.empno}
</select>
执行结果:
ename为空且job不为空
==> Preparing: UPDATE t_emp SET job=? WHERE empno=?
==> Parameters: mannager(String), 7100(Integer) job为空且ename不为空
==> Preparing: UPDATE t_emp SET ename=? WHERE empno=?
==> Parameters: itpsc2(String), 7100(Integer) job和ename都不为空
==> Preparing: UPDATE t_emp SET ename=?,job=? WHERE empno=?
==> Parameters: itpsc2(String), mannager(String), 7100(Integer)
foreach 语句
需求:根据员工编号列表查询员工信息。7369,7499,7521。
Sql的写法是:select * from t_emp where 1=1 and empno=7369 or empno=7499 or empno=7521
mybatis的foreach语句可以帮我们实现类似功能。
<select id="queryByIds"
parameterType="com.itpsc.request.IdRequest" resultType="com.itpsc.vo.EmpVo">
SELECT * FROM t_emp
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
empno=#{id}
</foreach>
</where>
</select>
collection:指定输入对象中的集合属性
item:每次遍历生成的对象
open:开始遍历时的拼接字符串
close:结束时拼接的字符串
separator:遍历对象之间需要拼接的字符串
运行结果:
==> Preparing: SELECT * FROM t_emp WHERE ( empno=? or empno=? or empno=? )
==> Parameters: 7369(Integer), 7499(Integer), 7521(Integer)
<== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
<== Row: 7369, SMITH, CLERK, 7902, 1980-12-17, 800.00, null, 20
<== Row: 7499, ALLEN, SALESMAN, 7698, 1981-02-20, 1600.00, 300.00, 30
<== Row: 7521, WARD, SALESMAN, 7698, 1981-02-22, 1250.00, 500.00, 30
<== Total: 3
sql片段
将上面动态sql代码块抽取出来,组成一个sql片段,其它的statement中就可以引用该sql片段。提供代码复用性,方便团队成员之间进行开发。
<select id="queryCount2" parameterType="com.itpsc.request.EmpRequest" resultType="int">
SELECT count(*) FROM t_emp
<where>
<if test="emp!=null">
<if test="emp.deptno!=null">
and emp.deptno=#{emp.deptno}
</if>
<if test="emp.ename!=null">
and emp.ename=#{emp.ename}
</if>
<if test="emp.job!=null">
and emp.job=#{emp.job}
</if>
</if>
</where>
</select>
上面where语句中代码,我们可以通过<sql>标签封装成一个sql片段,然后在其它statement中通过<include>引用。
<sql id="querySql">
<if test="emp!=null">
<if test="emp.deptno!=null">
and emp.deptno=#{emp.deptno}
</if>
<if test="emp.ename!=null">
and emp.ename=#{emp.ename}
</if>
<if test="emp.job!=null">
and emp.job=#{emp.job}
</if>
</if>
</sql> <select id="queryCount2" parameterType="com.itpsc.request.EmpRequest" resultType="int">
SELECT count(*) FROM t_emp
<where>
<include refid="querySql"></include>
</where>
</select>
本文到此,下篇 mybatis基础系列(四)——关联查询、延迟加载、一级缓存与二级缓存。
mybatis基础系列(三)——动态sql的更多相关文章
- mybatis基础系列(四)——关联查询、延迟加载、一级缓存与二级缓存
关本文是Mybatis基础系列的第四篇文章,点击下面链接可以查看前面的文章: mybatis基础系列(三)——动态sql mybatis基础系列(二)——基础语法.别名.输入映射.输出映射 mybat ...
- mybatis基础系列(二)——基础语法、别名、输入映射、输出映射
增删改查 mapper根节点及其子节点 mybatis框架需要读取映射文件创建会话工厂,映射文件是以<mapper>作为根节点,在根节点中支持9个元素,分别为insert.update.d ...
- MyBatis学习总结_11_MyBatis动态Sql语句
MyBatis中对数据库的操作,有时要带一些条件,因此动态SQL语句非常有必要,下面就主要来讲讲几个常用的动态SQL语句的语法 MyBatis中用于实现动态SQL的元素主要有: if choose(w ...
- SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型
原文:SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server ...
- mybatis入门系列三之类型转换器
mybatis入门系列三之类型转换器 类型转换器介绍 mybatis作为一个ORM框架,要求java中的对象与数据库中的表记录应该对应 因此java类名-数据库表名,java类属性名-数据库表字段名, ...
- mybatis基础系列(一)——mybatis入门
好久不发博客了,写博文的一个好处是能让心静下来,整理下之前学习过的一些知识一起分享,大神路过~ mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射. ...
- Spring mybatis源码篇章-动态SQL节点源码深入
通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-动态SQL基础语法以及原理 前话 前文描述到通过mybatis默认的解析驱动类org.apache.ibat ...
- MyBatis学习系列三——结合Spring
目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring MyBatis在项目中应用一般都要结合Spring,这一章主要把MyBat ...
- 【C++自我精讲】基础系列三 重载
[C++自我精讲]基础系列三 重载 0 前言 分二部分:函数重载,操作符重载. 1 函数重载 函数重载:指在同一名字空间中,函数名称相同,参数类型.顺序或数量不同的一类函数,同一函数名的函数能完成不同 ...
随机推荐
- 在 浏览器中调用外接设备— —手写板 【win10 x64 手动注册ocx控件的方法】
PPAXSignToolSDK.ocx 浏览器下使用手写板时调用的控件,使用前必须先注册,,不然浏览器下版本无法正常工作. ocx 控件在安装包运行时会自动注册,如果安装包没有注册成功,需要进行手动注 ...
- 【协议】2、TCP/IP协议三次握手与四次握手流程解析
一.TCP报文格式 TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图:图1 TCP报文格式 上图中有几个字段需要重点介绍下: (1)序号:Seq序 ...
- That Nice Euler Circuit(LA3263+几何)
That Nice Euler Circuit Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu D ...
- 手把手教你实现Confluence6.7.1安装与破解
Confluence是一个专业的企业知识管理与协同软件,也可以用于构建企业wiki. 一.准备工作 下载confluence6.7.1 wget https://downloads.atlassian ...
- 判断api请求方式
$curl_request = $_SERVER['REQUEST_METHOD']; //获取请求方式 if($curl_request == 'POST'){ echo post; }else i ...
- 如何判断页面是pc端还是移动端,进入不同的页面
vue判断是pc端还是移动端分别进入不同的页面 判断移动端代码如下: function IsPC(){ var userAgentInfo = navigator.userAgent; var Age ...
- Python 练习:三级菜单选择城市
info = { 'GuangDong':{ 'GuangZhou': ['TianHe', 'HaiZhu'], 'MaoMing': ['MaoNan', 'DianBai']}, 'ShanDo ...
- codechef QCHEF(不删除莫队)
题意 题目链接 给出长度为\(n\)的序列,每次询问区间\([l, r]\),要求最大化 \(max |x − y| : L_i ≤ x, y ≤ R_i and A_x = A_y\) Sol 标算 ...
- 2017-12-22 日语编程语言"抚子"-第三版实现初探
前文日语编程语言"抚子" - 第三版特色初探仅对语言的语法进行了初步了解. 之前的语言原型实现尝试(如编程语言试验之Antlr4+JavaScript实现"圈4" ...
- php使用PHPexcel类读取excel文件(循环读取每个单元格的数据)
error_reporting(E_ALL); date_default_timezone_set('Asia/ShangHai'); include_once('Classes/PHPExcel/I ...