MyBatis编写动态SQL实例

 更新时间:2026年05月26日 10:09:50   作者:小七mod  
这篇文章主要介绍了MyBatis编写动态SQL实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

动态 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

多条件分支判断

Trimwhereset

辅助元素

用于处理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调用类的静态字段值

十、总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Node.js对MySQL数据库的增删改查实战记录

    Node.js对MySQL数据库的增删改查实战记录

    这篇文章主要给大家介绍了关于Node.js对MySQL数据库的增删改查的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作介绍的非常详细,需要的朋友可以参考下
    2021-10-10
  • 一文总结MySQL中数学函数有哪些

    一文总结MySQL中数学函数有哪些

    MySQL函数包括数学函数、字符串函数、日期和时间函数、条件判断函数、系统信息函数、加密函数等,下面这篇文章主要给大家介绍了关于MySQL中数学函数有哪些的相关资料,需要的朋友可以参考下
    2023-02-02
  • 一个 20 秒 SQL 慢查询优化处理方案

    一个 20 秒 SQL 慢查询优化处理方案

    这篇文章主要分享一个 20 秒 SQL 慢查询优化的经历与处理方案,页面无法正确获取数据,经排查原来是接口调用超时,而最后发现是因为SQL查询长达到20多秒而导致了问题的发生,下面来看问题具体介绍吧
    2022-01-01
  • MySQL使用MD5加密算法进行数据加密功能

    MySQL使用MD5加密算法进行数据加密功能

    在现代的数据库应用中,数据的安全性和隐私性变得尤为重要,MySQL作为最流行的关系型数据库之一,提供了多种加密功能,允许用户对数据进行加密和解密操作,在这篇文章中,我们将深入探讨MySQL的加密功能,并重点介绍如何使用MD5加密算法进行加密,需要的朋友可以参考下
    2024-12-12
  • mysql sum(if())和count(if())的用法说明

    mysql sum(if())和count(if())的用法说明

    这篇文章主要介绍了mysql sum(if())和count(if())的用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • MySQL8.0实现窗口函数计算同比环比

    MySQL8.0实现窗口函数计算同比环比

    本文主要介绍了MySQL8.0实现窗口函数计算同比环比,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • MySQL的时间差函数(TIMESTAMPDIFF、DATEDIFF)、日期转换计算函数(date_add、day、date_format、str_to_date)

    MySQL的时间差函数(TIMESTAMPDIFF、DATEDIFF)、日期转换计算函数(date_add、day、da

    这篇文章主要介绍了MySQL的时间差函数(TIMESTAMPDIFF、DATEDIFF)、日期转换计算函数(date_add、day、date_format、str_to_date),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • Mysql 5.7.17 winx64免安装版,win10环境下安装配置图文教程

    Mysql 5.7.17 winx64免安装版,win10环境下安装配置图文教程

    这篇文章主要介绍了Mysql 5.7.17 winx64免安装版,win10环境下安装配置图文教程,需要的朋友可以参考下
    2017-01-01
  • Windows下mysql5.7.10安装配置方法图文教程

    Windows下mysql5.7.10安装配置方法图文教程

    这篇文章主要为大家详细介绍了Windows上mysql5.7.10安装配置方法图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • MySQL性能压力基准测试工具sysbench的使用简介

    MySQL性能压力基准测试工具sysbench的使用简介

    这篇文章主要介绍了MySQL性能压力基准测试工具sysbench的使用简介,帮助大家更好的理解和学习使用MySQL,感兴趣的朋友可以了解下
    2021-04-04

最新评论