对于曾经手动拼接JDBC SQL语句的开发者而言,其中的繁琐与易错令人印象深刻。需要时刻注意空格和末尾逗号,稍有不慎就会导致SQL执行错误。MyBatis的动态SQL功能正是为了解决这类重复性劳动而设计的强大特性。 动态SQL本身具有一定复杂性,但MyBatis通过一套基于XML的标签语言显著降低了
MyBatis动态SQL编写实例教程
时间:2026-05-26
浏览:433
文章目录
对于曾经手动拼接JDBC SQL语句的开发者而言,其中的繁琐与易错令人印象深刻。需要时刻注意空格和末尾逗号,稍有不慎就会导致SQL执行错误。MyBatis的动态SQL功能正是为了解决这类重复性劳动而设计的强大特性。

动态SQL本身具有一定复杂性,但MyBatis通过一套基于XML的标签语言显著降低了使用难度。熟悉JSTL或类似模板语言的开发者会对这些标签感到亲切。在MyBatis 3版本中,得益于OGNL表达式的引入,核心标签库得以精简,目前需要掌握的主要标签包括以下几类:
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
- bind
- sql片段
以下是这些核心动态SQL元素的快速参考表:
|
元素 |
作用 |
备注 |
|
if |
条件判断 |
用于单条件分支判断 |
|
choose、when、otherwise |
多条件分支判断 |
类似于Java中的switch-case结构 |
|
Trim、where、set |
SQL语句辅助处理 |
用于智能处理SQL拼接中的关键字和分隔符 |
|
foreach |
集合遍历 |
常用于IN查询和批量操作 |
MyBatis动态SQL之if标签
if标签是动态SQL中最基础且常用的元素。例如,根据员工对象的不同属性进行动态查询的示例如下:
EmpDao.xml
对应的接口与测试代码:
EmpDao.java
public ListgetEmpByCondition(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 empByCondition = mapper.getEmpByCondition(emp);
for (Emp emp1 : empByCondition) {
System.out.println(emp1);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
上述写法存在一个常见问题:当某些条件为空时,SQL末尾可能残留多余的“AND”关键字,或者WHERE后无任何条件,导致语法错误。传统的解决方法是添加“1=1”条件,但这可能带来SQL注入风险并影响查询性能。MyBatis提供了更优雅的解决方案——where标签。
MyBatis动态SQL之where标签
where标签能够智能地处理WHERE子句:仅当包含的条件有返回内容时才插入WHERE关键字,并自动移除子句开头多余的AND或OR。
使用where标签重写上述示例:
核心功能:自动管理WHERE关键字及条件连接词。
需要注意两点:
- 第一个if条件中的“and”可写可不写,where标签会自动处理。后续条件的连接词必须明确指定。
- 若所有条件均不满足,where标签不会生成任何内容,SQL变为查询全部数据。
MyBatis动态SQL之trim标签
trim标签是where和set标签的通用化版本,功能更为强大灵活。它允许自定义前缀、后缀,并去除首尾指定的多余字符。
使用trim模拟where标签功能:
属性说明:
- `prefix="where"`:在生成的SQL片段前添加WHERE关键字。
- `prefixOverrides="and"`:若片段以“and”开头,则自动移除。
- `suffixOverrides="and"`:若片段以“and”结尾,则自动移除。
trim标签在复杂场景中尤其有用,例如动态构建包含OR连接的复合条件:
OR FIND_IN_SET( #{idItem}, space_types )
此代码会智能生成如`and ( OR OR )`的结构,确保语法正确性。
MyBatis动态SQL之foreach标签
foreach标签用于遍历集合,常见于IN查询或批量操作场景。
关于MyBatis批量操作,常有两种实现方式:
- 使用foreach标签动态拼接SQL语句(如批量插入),通常效率较高。
- 使用MyBatis的BATCH类型执行器,在提交时批量执行语句。
MyBatis动态SQL之choose、when、otherwise标签
这组标签类似于Java中的switch-case结构,用于从多个条件中仅选择其一执行。
执行逻辑为按顺序判断when条件,首个满足的条件对应的SQL会被采用,后续条件被忽略。若所有when均不满足,则使用otherwise中的内容。
MyBatis动态SQL之set标签
set标签用于动态更新语句,其作用类似于where标签。它会智能插入SET关键字,并自动处理字段末尾多余的逗号。
update emp empno=#{empno}, ename = #{ename}, sal = #{sal} empno = #{empno}
即使最后一个更新条件不满足,set标签也会自动移除前一个字段后的逗号,保证SQL语法正确。
MyBatis动态SQL之bind标签
bind标签允许创建变量并绑定到OGNL上下文,常用于对参数进行预处理,例如拼接模糊查询的通配符。
这种方式将处理逻辑置于XML配置中,有利于代码解耦和数据库兼容性。
MyBatis动态SQL之sql与include标签
sql标签用于定义可重用的SQL片段,通过include标签引入,能有效减少代码重复,提升可维护性。
定义SQL片段:
${alias}.id,${alias}.username,${alias}.password
在查询中引用该片段:
MyBatis动态SQL常用OGNL表达式
动态SQL标签的test属性基于OGNL表达式进行判断。以下是常用的OGNL表达式:
- 逻辑运算: `e1 or e2`, `e1 and e2`, `!e` 或 `not e`
- 相等判断: `e1 == e2` (值比较), `e1 eq e2` (字符串比较)
- 不等判断: `e1 != e2`, `e1 neq e2`
- 比较运算: `e1 lt e2` (小于), `e1 lte e2` (小于等于), `gt` (大于), `gte` (大于等于)
- 集合判断: `e1 in e2`, `e1 not in e2`
- 算术运算: `e1 + e2`, `e1 * e2`, `e1/e2`, `e1 - e2`, `e1%e2`
- 调用与访问: `e.method(args)` (调用方法), `e.property` (访问属性), `e1[e2]` (按索引取值)
- 静态调用: `@class@method(args)` (调用静态方法), `@class@field` (访问静态字段)
MyBatis动态SQL总结
MyBatis动态SQL通过一系列标签,将开发者从复杂的SQL字符串拼接中解放出来。从基础的条件判断(if)到多分支选择(choose),再到智能的语法处理(where, set, trim),以及集合遍历(foreach)和代码复用(sql),构成了一套完整灵活的解决方案。熟练掌握这些标签是编写高效、可维护MyBatis映射文件的关键。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。