MyBatis动态SQL编写实例教程

作者:技术拾光

时间:2026-05-26

浏览:433

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

文章目录

对于曾经手动拼接JDBC SQL语句的开发者而言,其中的繁琐与易错令人印象深刻。需要时刻注意空格和末尾逗号,稍有不慎就会导致SQL执行错误。MyBatis的动态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 List 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 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关键字及条件连接词。

需要注意两点:

  1. 第一个if条件中的“and”可写可不写,where标签会自动处理。后续条件的连接词必须明确指定。
  2. 若所有条件均不满足,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批量操作,常有两种实现方式:

  1. 使用foreach标签动态拼接SQL语句(如批量插入),通常效率较高。
  2. 使用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映射文件的关键。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章