本文是Mybatis基础系列的第三篇文章,点击下面链接可以查看前面的文章:

mybatis基础系列(二)——基础语法、别名、输入映射、输出映射

mybatis基础系列(一)——mybatis入门

动态sql

MyBatis 的强大特性之一便是它的动态 SQL。摆脱了JDBC中根据不同条件拼接 SQL 语句的痛苦。动态 SQL可以帮我们解决复杂需求。mybatis 动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach等标签组合成非常灵活的SQL语句。

根据员工编号或者员工姓名查询员工信息,输入的员工编号可能为空。

  1. <select id="queryByEnameOrEempno" parameterType="com.itpsc.request.EmpRequest" resultType="com.itpsc.vo.EmpVo">
  2. SELECT * FROM t_emp WHERE
  3. <if test="emp.ename!=null">
  4. ename=#{emp.ename}
  5. </if>
  6. <if test="emp.empno!=null">
  7. and empno=#{emp.empno}
  8. </if>
  9. </select>

执行结果:

  1. 编号为空
  2. ==> Preparing: SELECT * FROM t_emp WHERE ename=?
  3. ==> Parameters: itpsc(String)
  4. <== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
  5. <== Row: 7100, itpsc, developer, 7902, 1980-01-10, null, 1000.00, 20
  6. <== Total: 1
  7. 姓名为空
  8. ==> Preparing: SELECT * FROM t_emp WHERE and empno=?
  9. ==> Parameters: 7100(Integer)

从执行结果可以看出,上面的if语句只能是在员工姓名不能为空的情况下执行,如果员工姓名为空sql语句就出错了,If+where语句可以解决这个问题。

if+where语句与trim 语句

  1. <select id="queryByEnameOrEempno" parameterType="com.itpsc.request.EmpRequest" resultType="com.itpsc.vo.EmpVo">
  2. SELECT * FROM t_emp
  3. <where>
  4. <if test="emp.ename!=null">
  5. and ename=#{emp.ename}
  6. </if>
  7. <if test="emp.empno!=null">
  8. and empno=#{emp.empno}
  9. </if>
  10. </where>
  11. </select>

执行结果:

  1. 姓名为空
  2. ==> Preparing: SELECT * FROM t_emp WHERE empno=?
  3. ==> Parameters: 7100(Integer)
  4. <== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
  5. <== Row: 7100, itpsc, developer, 7902, 1980-01-10, null, 1000.00, 20
  6. <== Total: 1
  7. 编号为空
  8. ==> Preparing: SELECT * FROM t_emp WHERE ename=?
  9. ==> Parameters: itpsc(String)
  10. <== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
  11. <== Row: 7100, itpsc, developer, 7902, 1980-01-10, null, 1000.00, 20
  12. <== Total: 1

<where>标签中包含的标签中有返回值的话,它就插入一个where关键字,并且where 标签会自动将其后第一个条件的and或者是or给忽略掉。

trim语句可以实现<where>标签类似的功能:

(1)trim标签可以在包含的内容前加上前缀,也可以在其后加上后缀,对应的属性是prefix和suffix;

(2)trim标签可以把包含内容的首部某些内容忽略,也可以把尾部的某些内容忽略,对应的属性是prefixOverrides和suffixOverrides。

  1. <select id="queryByEnameOrEempno" parameterType="com.itpsc.request.EmpRequest" resultType="com.itpsc.vo.EmpVo">
  2. SELECT * FROM t_emp
  3. <trim prefix="where" prefixOverrides="and | or">
  4. <if test="emp.ename!=null">
  5. and ename=#{emp.ename}
  6. </if>
  7. <if test="emp.empno!=null">
  8. and empno=#{emp.empno}
  9. </if>
  10. </trim>
  11. </select>

执行结果:

  1. empno为空
  2. ==> Preparing: SELECT * FROM t_emp where ename=?
  3. ==> Parameters: itpsc2(String)
  4. <== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
  5. <== Row: 7101, itpsc2, developer, 7902, 1980-01-10, 2000.00, 1000.00, 20
  6. <== Total: 1
  7.  
  8. ename为空
  9. ==> Preparing: SELECT * FROM t_emp where empno=?
  10. ==> Parameters: 7100(Integer)
  11. <== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
  12. <== Row: 7100, itpsc1, mannager, 7902, 1980-01-10, null, 1000.00, 20
  13. <== Total: 1
  14.  
  15. empnoename都不为空
  16. ==> Preparing: SELECT * FROM t_emp where ename=? and empno=?
  17. ==> Parameters: itpsc2(String), 7100(Integer)
  18. <== Total: 0

if+set语句与trim语句

条件判断用<where>标签,同理更新操作用<set>标签。

  1. <select id="updateEnameOrJob" parameterType="com.itpsc.request.EmpRequest">
  2. UPDATE t_emp
  3. <set>
  4. <if test="emp.ename!=null">
  5. ename=#{emp.ename}
  6. </if>
  7. <if test="emp.job!=null">
  8. job=#{emp.job}
  9. </if>
  10. </set>
  11. WHERE empno=#{emp.empno}
  12. </select>

运行结果:

  1. job为空
  2. ==> Preparing: UPDATE t_emp SET ename=? WHERE empno=?
  3. ==> Parameters: hello(String), 7100(Integer)
  4. ename 为空
  5. ==> Preparing: UPDATE t_emp SET job=? WHERE empno=?
  6. ==> Parameters: itpsc(String), 7100(Integer)

<set>标签中包含的标签中有返回值的话,它就插入一个set关键字。job和ename都不为空则sql错误,那又如何写呢,trim标签可以帮我们能实现。

  1. <select id="updateEnameOrJob" parameterType="com.itpsc.request.EmpRequest">
  2. UPDATE t_emp
  3. <trim prefix="set" suffixOverrides=",">
  4. <if test="emp.ename!=null">
  5. ename=#{emp.ename},
  6. </if>
  7. <if test="emp.job!=null">
  8. job=#{emp.job},
  9. </if>
  10. </trim>
  11. WHERE empno=#{emp.empno}
  12. </select>

运行结果:

  1. ==> Preparing: UPDATE t_emp set ename=?, job=? WHERE empno=?
  2. ==> Parameters: itpsc(String), mannager(String), 7100(Integer)

choose(when,otherwise) 语句

上的例子中,job和ename都不为空则是一种条件,job为空且ename不为空是一种条件,ename为空且job不为空是一种条件。实际上,我们要只要满足任意一个条件,就可以执行。choose(when,otherwise) 语句可以帮我们解决,类似jstl。

  1. <select id="updateEnameOrJob" parameterType="com.itpsc.request.EmpRequest">
  2. UPDATE t_emp
  3. <set>
  4. <choose>
  5. <when test="emp.ename!=null and emp.job!=null">
  6. ename=#{emp.ename},job=#{emp.job}
  7. </when>
  8. <otherwise>
  9. <if test="emp.ename!=null">
  10. ename=#{emp.ename}
  11. </if>
  12. <if test="emp.job!=null">
  13. job=#{emp.job}
  14. </if>
  15. </otherwise>
  16. </choose>
  17. </set>
  18. WHERE empno=#{emp.empno}
  19. </select>

执行结果:

  1. ename为空且job不为空
  2. ==> Preparing: UPDATE t_emp SET job=? WHERE empno=?
  3. ==> Parameters: mannager(String), 7100(Integer)
  4.  
  5. job为空且ename不为空
  6. ==> Preparing: UPDATE t_emp SET ename=? WHERE empno=?
  7. ==> Parameters: itpsc2(String), 7100(Integer)
  8.  
  9. jobename都不为空
  10. ==> Preparing: UPDATE t_emp SET ename=?,job=? WHERE empno=?
  11. ==> 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语句可以帮我们实现类似功能。

  1. <select id="queryByIds"
  2. parameterType="com.itpsc.request.IdRequest" resultType="com.itpsc.vo.EmpVo">
  3. SELECT * FROM t_emp
  4. <where>
  5. <foreach collection="ids" item="id" open="and (" close=")" separator="or">
  6. empno=#{id}
  7. </foreach>
  8. </where>
  9. </select>

collection:指定输入对象中的集合属性

item:每次遍历生成的对象

open:开始遍历时的拼接字符串

close:结束时拼接的字符串

separator:遍历对象之间需要拼接的字符串

运行结果:

  1. ==> Preparing: SELECT * FROM t_emp WHERE ( empno=? or empno=? or empno=? )
  2. ==> Parameters: 7369(Integer), 7499(Integer), 7521(Integer)
  3. <== Columns: empno, ename, job, mgr, hiredate, sal, comm, deptno
  4. <== Row: 7369, SMITH, CLERK, 7902, 1980-12-17, 800.00, null, 20
  5. <== Row: 7499, ALLEN, SALESMAN, 7698, 1981-02-20, 1600.00, 300.00, 30
  6. <== Row: 7521, WARD, SALESMAN, 7698, 1981-02-22, 1250.00, 500.00, 30
  7. <== Total: 3

sql片段

将上面动态sql代码块抽取出来,组成一个sql片段,其它的statement中就可以引用该sql片段。提供代码复用性,方便团队成员之间进行开发。

  1. <select id="queryCount2" parameterType="com.itpsc.request.EmpRequest" resultType="int">
  2. SELECT count(*) FROM t_emp
  3. <where>
  4. <if test="emp!=null">
  5. <if test="emp.deptno!=null">
  6. and emp.deptno=#{emp.deptno}
  7. </if>
  8. <if test="emp.ename!=null">
  9. and emp.ename=#{emp.ename}
  10. </if>
  11. <if test="emp.job!=null">
  12. and emp.job=#{emp.job}
  13. </if>
  14. </if>
  15. </where>
  16. </select>

上面where语句中代码,我们可以通过<sql>标签封装成一个sql片段,然后在其它statement中通过<include>引用。

  1. <sql id="querySql">
  2. <if test="emp!=null">
  3. <if test="emp.deptno!=null">
  4. and emp.deptno=#{emp.deptno}
  5. </if>
  6. <if test="emp.ename!=null">
  7. and emp.ename=#{emp.ename}
  8. </if>
  9. <if test="emp.job!=null">
  10. and emp.job=#{emp.job}
  11. </if>
  12. </if>
  13. </sql>
  14.  
  15. <select id="queryCount2" parameterType="com.itpsc.request.EmpRequest" resultType="int">
  16. SELECT count(*) FROM t_emp
  17. <where>
  18. <include refid="querySql"></include>
  19. </where>
  20. </select>

本文到此,下篇 mybatis基础系列(四)——关联查询、延迟加载、一级缓存与二级缓存。

mybatis基础系列(三)——动态sql的更多相关文章

  1. mybatis基础系列(四)——关联查询、延迟加载、一级缓存与二级缓存

    关本文是Mybatis基础系列的第四篇文章,点击下面链接可以查看前面的文章: mybatis基础系列(三)——动态sql mybatis基础系列(二)——基础语法.别名.输入映射.输出映射 mybat ...

  2. mybatis基础系列(二)——基础语法、别名、输入映射、输出映射

    增删改查 mapper根节点及其子节点 mybatis框架需要读取映射文件创建会话工厂,映射文件是以<mapper>作为根节点,在根节点中支持9个元素,分别为insert.update.d ...

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

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

  4. SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型

    原文:SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server ...

  5. mybatis入门系列三之类型转换器

    mybatis入门系列三之类型转换器 类型转换器介绍 mybatis作为一个ORM框架,要求java中的对象与数据库中的表记录应该对应 因此java类名-数据库表名,java类属性名-数据库表字段名, ...

  6. mybatis基础系列(一)——mybatis入门

    好久不发博客了,写博文的一个好处是能让心静下来,整理下之前学习过的一些知识一起分享,大神路过~ mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射. ...

  7. Spring mybatis源码篇章-动态SQL节点源码深入

    通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-动态SQL基础语法以及原理 前话 前文描述到通过mybatis默认的解析驱动类org.apache.ibat ...

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

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

  9. 【C++自我精讲】基础系列三 重载

    [C++自我精讲]基础系列三 重载 0 前言 分二部分:函数重载,操作符重载. 1 函数重载 函数重载:指在同一名字空间中,函数名称相同,参数类型.顺序或数量不同的一类函数,同一函数名的函数能完成不同 ...

随机推荐

  1. oracle sql优化的几种方法

    1.最基本最简单的方式是减少访问数据库的次数.oracle在内部执行了许多工作,比如解析SQL语句, 估算索引的利用率,  读数据块等等,都将大量耗费oracle数据库的运行 2.选择最有效率的表名顺 ...

  2. python之常用模块补充

    namedtuple 命名元组 ->类似创建了一个类 from collections import namedtuple p = namedtuple("point", [ ...

  3. K-Means算法的10个有趣用例

    https://www.jianshu.com/p/162c9ec713cf 摘要: 让我们走进K-Means算法的“前世今生”以及和它有关的十个有趣的应用案例. K-means算法具有悠久的历史,并 ...

  4. 免费工资总额管控系统-JXHR2016

    •工资总额是指按照国家统计局规定的统计口径或企业规定,在一定时期内支付给各类用工的劳动报酬总额 •工资总额,即基本工资,包括岗位工资.各项津补贴 •JXHR2016以薪酬管控为核心,结合人力资源规划. ...

  5. Ansible--配置文件及系列命令

    Ansible目录结构 安装完成ansible后要知道ansible主要安装的了什么,安装的目录结构是什么,每个目录做什么的 可以使用:rpm -ql ansible | less 来查看ansibl ...

  6. 安卓开发_浅谈WebView(转)

    ,有一个功能需要在APP中调用网站 百度了一下,发现需要用WebView来实现 实现方法很容易,我就不在这里写一遍了 ,直接转一下我学习的内容吧 原创作品,允许转载,转载时请务必以超链接形式标明文章  ...

  7. 安卓开发_计时器(Chronometer)的简单使用

    计时器控件(Chronometer)是一个可以显示从某个起始时间开始一共过去多长时间的本文. 继承自TextView,以文本的形式显示时间内容 该组件有五个方法 1.setBase(): \\用于设置 ...

  8. python变量的命名空间

    首先必须要提一下python程序执行过程中变量的查找规则 较官方的查找机制是: 局部作用域--外部函数作用域--全局作用域--内建函数作用域 其实一般内建函数中的作用域很少会涉及到,因为内建函数其实是 ...

  9. JavaScript大杂烩15 - 使用JQuery(下)

    前面我们总结了使用各种selector拿到了jQuery对象了,下面就是对这个对象执行指定的行为了. 2. 操作对象 - 行为函数action 执行jQuery内置的行为函数的时候,JQuery自动遍 ...

  10. SQL Server 2005详细安装过程及配置

    说明:个人感觉SQL Server 2005是目前所有的SQL Server版本当中最好用的一个版本了,原因就是这个版本比起其它版本来说要安装简单,操作简便,只可惜这个版本只能在Windows7或者低 ...