最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
MyBatis动态SQL编写实例
时间:2026-07-05 10:42:00 编辑:袖梨 来源:一聚教程网
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。
在 MyBatis 之前的版本中,需要花时间了解大量的元素。
借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的标签元素种类比原来的一半还要少:
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
- bind
- sql片段
元素 | 作用 | 备注 |
if | 判断语句 | 单条件分支判断 |
choose、when、otherwise | 相当于java的case when | 多条件分支判断 |
Trim 、 where 、 set | 辅助元素 | 用于处理sql拼装问题 |
foreach | 循环语句 | 在in语句等列举条件常用,常用于实现批量操作 |
一、if
EmpDao.xml
<select id="getEmpByCondition" resultType="cn.tulingxueyuan.bean.Emp"> select * from emp where <if test="empno!=null"> empno > #{empno} and </if> <if test="ename!=null"> ename like #{ename} and </if> <if test="sal!=null"> sal > #{sal} </if></select>EmpDao.java
public List<Emp> getEmpByCondition(Emp emp);
Test.java
@Test public void test10() { SqlSession sqlSession = sqlSessionFactory.openSession(); try { EmpDao mapper = sqlSession.getMapper(EmpDao.class); Emp emp = new Emp(); emp.setEmpno(6500); emp.setEname("%E%"); emp.setSal(500.0); List<Emp> empByCondition = mapper.getEmpByCondition(emp); for (Emp emp1 : empByCondition) { System.out.println(emp1); } } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); }}看起来测试是比较正常的,但是大家需要注意的是如果我们传入的参数值有缺失会怎么呢?这个时候拼接的sql语句就会变得有问题,例如不传参数或者丢失最后一个参数,那么语句中就会多一个where或者and的关键字。
可以通过在where条件的最前面加上"1 = 1"来解决这个问题。加入条件“1=1”后,既保证了where后面的条件成立,又避免了where后面第一个词是and或者or之类的关键词。但是这样写虽然可以实现功能,但存在SQL注入的风险,而且可能会造成索引失效全表扫描。
因此MyBatis提供了where标签可以代替where 1=1。
二、where
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
<select id="getEmpByCondition" resultType="cn.tulingxueyuan.bean.Emp"> select * from emp <where> <if test="empno!=null"> empno > #{empno} </if> <if test="ename!=null"> and ename like #{ename} </if> <if test="sal!=null"> and sal > #{sal} </if> </where></select>【作用】
自动去除首个条件中的“AND”或“OR”
注:
1、按照标准写法,第一个if标签内的AND应该不写,但是,就算开发中书写也不会报错。因为where标签会自动的移除了第一个AND链接。但是,第二个之后的if标签内,必须有AND链接。
2、如果没有一个条件符合,则返回所有条目。
三、trim
该标签的功能与where类似,并且额外的提供了前缀后缀功能。具体用法如下:
<!-- trim截取字符串: prefix:前缀,为sql整体添加一个前缀 prefixOverrides:去除整体字符串前面多余的字符 suffixOverrides:去除后面多余的字符串--><select id="getEmpByCondition" resultType="cn.tulingxueyuan.bean.Emp"> select * from emp <trim prefix="where" prefixOverrides="and" suffixOverrides="and"> <if test="empno!=null"> empno > #{empno} and </if> <if test="ename!=null"> ename like #{ename} and </if> <if test="sal!=null"> sal > #{sal} and </if> </trim></select>【作用】
1、可以用trim替代where标签。
2、属性 prefix=“where”,表示:加前缀 where。
3、属性 suffix=“)”,表示:加后缀 )。
4、属性 prefixOverrides=“and|or”,前缀覆盖:自动覆盖第一个and或者or。
5、属性 suffixOverrides=“”,后缀覆盖:去掉整个字符串后面多余的字符。
trim扩展
trim标签的使用场景比where更多,如下:
<if test="params.businessTypeList != null and params.businessTypeList.size() > 0 "> <trim prefix="and ( " prefixOverrides="AND|OR" suffix=" )"> <foreach collection="params.businessTypeList" item="idItem" index="index"> OR FIND_IN_SET( #{idItem}, space_types ) </foreach> </trim></if>在循环的时候拼接多个sql条件,用trim标签的prefixOverrides属性覆盖第一个and或者or,前缀加上"and (“,后缀加上” )",动态生成一个条件满足多种情况的sql。
四、foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。
<!--foreach是对集合进行遍历 collection="deptnos" 指定要遍历的集合 close="" 表示以什么结束 index="" 给定一个索引值 item="" 遍历的每一个元素的值 open="" 表示以什么开始 separator="" 表示多个元素的分隔符--><select id="getEmpByDeptnos" resultType="Emp"> select * from emp where deptno in <foreach collection="deptnos" close=")" index="idx" item="deptno" open="(" separator=","> #{deptno} </foreach></select>高频面试题:通过Mybatis怎么样进行批量的操作
- 通过foreach动态拼装SQL语句(这个速度跟快更快,因为只和数据库交互一次)
- 使用BATCH类型的excutor
五、choose、when、otherwise
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
<select id="getEmpByConditionChoose" resultType="cn.tulingxueyuan.bean.Emp"> select * from emp <where> <choose> <when test="empno!=null"> empno > #{empno} </when> <when test="ename!=null"> ename like #{ename} </when> <when test="sal!=null"> sal > #{sal} </when> <otherwise> 1=1 </otherwise> </choose> </where></select>六、set
用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。
<update id="updateEmpByEmpno"> update emp <set> <if test="empno!=null"> empno=#{empno}, </if> <if test="ename!=null"> ename = #{ename}, </if> <if test="sal!=null"> sal = #{sal} </if> </set> <where> empno = #{empno} </where></update>七、bind
bind 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。
比如:
<select id="selectBlogsLike" resultType="Blog"> <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" /> SELECT * FROM BLOG WHERE title LIKE #{pattern}</select>八、sql
sql元素:用来定义可重用的 SQL 代码段,可以包含在其他语句中;
这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值。比如:
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>这个 SQL 片段可以在其它语句中使用,例如:
<select id="selectUsers" resultType="map"> select <include refid="userColumns"><property name="alias" value="t1"/></include>, <include refid="userColumns"><property name="alias" value="t2"/></include> from some_table t1 cross join some_table t2</select>
九、MyBatis常用OGNL表达式
OGNL表达式表达式就是写在if标签里面的那些判断条件。
- e1 or e2
- e1 and e2
- e1 == e2 判断值是否相同
- e1 eq e2 判断字符串是否相同
- e1 != e2 判断值是否不相等
- e1 neq e2 判断字符串是否不相等
- e1 lt e2 小于
- e1 lte e2 小于等于
- gt 大于
- gte 大于等于
- e1 in e2 判断e1是否在e2集合中
- e1 not in e2
- e1 + e2, e1 * e2, e1/e2, e1 - e2, e1%e2
- !e 非运算,求反
- not e 同上
- e.method(args) 调用对象方法
- e.property 对象属性值
- e1[e2]按索引取值,List,数组和Map
- @class@method(args)调用类的静态方法
- @class@field调用类的静态字段值
十、总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持本站。
您可能感兴趣的文章:- MyBatis之动态SQL和缓存使用及说明
- mybatis动态SQL常用的标签使用及说明
- 一文详解MyBatis中动态SQL的封装原理与常用标签实战应用
- MyBatis动态SQL与MyBatis Generator插件使用教程
- MyBatis 中动态 SQL 的作用及执行原理解析
- MyBatis CRUD 常用动态 SQL 标签整理
相关文章
- 原神菈乌玛技能是什么 07-06
- 《和平精英》野牛青春冒险家怎么升级-野牛青春冒险家的升级方法 07-06
- 和平精英陀螺仪怎么玩 07-06
- 《燕云十六声》无相皇BOSS通关攻略 07-06
- 《心动小镇》全粉色泡泡位置介绍 07-06
- 空洞骑士丝之歌育母怎么逃课 07-06