MyBatis动态 SQL 的执行原理

devtools/2024/12/27 11:31:14/

MyBatis 动态 SQL 是 MyBatis 框架中的一个重要特性,它允许开发者根据条件动态地生成不同的 SQL 语句。通过使用动态 SQL,开发者可以根据传入的参数动态地构建 SQL 查询,这样就避免了写多个 SQL 语句,提升了代码的灵活性和可维护性。

1. 动态 SQL 的概念

动态 SQL 指的是 SQL 语句在运行时(而非编译时)根据传入的参数来动态决定 SQL 语句的内容。通过 MyBatis 提供的 <if>, <choose>, <foreach>, <where> 等标签,开发者可以根据不同的条件动态地生成 SQL 语句。

2. MyBatis 动态 SQL 的执行原理

MyBatis 在执行动态 SQL 时,主要的工作流程如下:

  1. SQL 映射文件解析

    • MyBatis 的映射文件(如 mapper.xml)中定义了动态 SQL 语句,这些 SQL 语句通常包含一些动态元素(例如 <if><choose><foreach> 等)。
    • 当执行某个映射方法时,MyBatis 会首先加载并解析对应的映射文件(mapper.xml)中的 SQL 语句。此时,SQL 语句中的动态部分并不会立即生成,只有当方法被调用时,MyBatis 会根据传入的参数来生成最终的 SQL 语句。
  2. 构建 SQL 语句

    • MyBatis 会将 SQL 语句中的动态部分替换为实际的 SQL 语句。例如:
      • <if> 标签根据条件来决定是否包含某部分 SQL。
      • <choose> 标签类似于 Java 中的 if-else,选择不同的 SQL 片段。
      • <foreach> 标签用于循环生成多个 SQL 片段,通常用于处理集合或数组。
    • MyBatis 会通过解析 parameterType 参数(例如,Map 或 POJO 对象)来判断条件和动态内容。
  3. SQL 语句生成

    • 动态部分通过 MyBatis 内部的 SQL 构建器生成最终的 SQL 语句。MyBatis 会使用 Java 的 OGNL(Object-Graph Navigation Language)表达式来获取参数的属性值,决定哪些 SQL 片段应该被包括在内。
  4. SQL 语句执行

    • 生成完整的 SQL 语句后,MyBatis 会交给数据库执行。
    • 这个 SQL 语句会根据数据库的返回结果进行映射,最终返回给应用程序。
  5. 返回结果

    • 执行 SQL 后,MyBatis 会根据 SQL 查询结果和映射文件中的映射规则,将查询结果封装为 Java 对象并返回。

3. MyBatis 动态 SQL 的常用标签

MyBatis 提供了丰富的标签来实现动态 SQL,以下是几个常用的标签及其作用:

(1) <if>
  • 作用:根据条件判断是否包括某部分 SQL 语句。

  • 用法:当条件为 true 时,包含该部分 SQL,否则跳过。

    <select id="findUser" resultType="User"> SELECT * FROM user WHERE 1 = 1 <if test="name != null"> AND name = #{name} </if> <if test="age != null"> AND age = #{age} </if> </select>

    这段代码中,只有在 nameage 不为 null 时,对应的 SQL 部分才会被加入。

(2) <choose><when><otherwise>
  • 作用:类似于 Java 中的 if-else 语句,根据不同的条件选择 SQL 片段。

    <select id="findUser" resultType="User"> SELECT * FROM user WHERE 1 = 1 <choose> <when test="name != null"> AND name = #{name} </when> <when test="age != null"> AND age = #{age} </when> <otherwise> AND status = 'ACTIVE' </otherwise> </choose> </select>

    如果 name 不为 null,会选择第一个 <when> 语句,否则会选择第二个 <when> 语句,如果都不满足条件,则执行 <otherwise> 语句。

(3) <foreach>
  • 作用:用于处理集合(如列表、数组)类型的参数,生成 SQL 语句中相应的重复部分。

    <select id="findUsersByIds" resultType="User"> SELECT * FROM user WHERE id IN <foreach item="id" collection="list" open="(" close=")" separator=","> #{id} </foreach> </select>

    这个 SQL 会将传入的 list 集合的每个元素都作为 id 值生成 IN 条件。

(4) <where>
  • 作用:用于自动为 SQL 添加 WHERE 关键字,并且处理 SQL 中的多余 ANDOR

    <select id="findUser" resultType="User"> <where> <if test="name != null">AND name = #{name}</if> <if test="age != null">AND age = #{age}</if> </where> </select>

    使用 <where> 后,MyBatis 会自动处理 ANDOR,避免 SQL 开头出现多余的 ANDOR

(5) <set>
  • 作用:用于更新 SQL 语句中的 SET 子句,自动处理逗号的添加与删除。

    <update id="updateUser"> UPDATE user <set> <if test="name != null">name = #{name},</if> <if test="age != null">age = #{age},</if> </set> WHERE id = #{id} </update>

    使用 <set> 标签后,MyBatis 会自动处理 SET 子句中的逗号问题。

4. MyBatis 动态 SQL 的执行过程

  1. SQL 语句生成:通过动态 SQL 标签(<if><foreach><choose><where> 等)构建最终的 SQL 语句。
  2. 传入参数:在执行查询时,MyBatis 会传入相应的参数,执行动态 SQL 时根据参数判断条件。
  3. 执行 SQL:生成最终的 SQL 后,MyBatis 会将其交给底层的数据库执行。
  4. 结果映射:执行结果会返回并映射为 Java 对象。

5. 总结

MyBatis 的动态 SQL 提供了强大的功能,使得开发者能够灵活地生成复杂的 SQL 查询。通过使用 <if>, <foreach>, <choose>, <set> 等标签,MyBatis 可以根据参数动态生成 SQL 语句,避免了写多个 SQL 的繁琐工作。理解 MyBatis 动态 SQL 的执行原理可以帮助你编写更灵活且高效的数据库操作代码。


http://www.ppmy.cn/devtools/145804.html

相关文章

五十五:服务器端的主动消息推送

随着互联网技术的发展&#xff0c;用户体验和实时性成为应用服务的重要指标。传统的客户端轮询&#xff08;polling&#xff09;模式逐渐无法满足实时数据更新的需求&#xff0c;而服务器端的主动消息推送技术应运而生&#xff0c;为开发者和用户带来了更高效的解决方案。 主动…

Pingpingping 解题思路

题目 源代码 <?php highlight_file(__FILE__); error_reporting(0); $_ping $_GET[Ping_ip.exe]; if(isset($_ping)){system("ping -c 3 ".$_ping); }else{$data base64_encode(file_get_contents("error.png"));echo "<img srcdata:image/…

如何编写 Prompt

如何编写 Prompt Prompt 示例参考 对于特定的任务来说&#xff0c;没有万能的Prompt&#xff0c;只有一些通用的模式&#xff0c;要完成这个任务还需要这个任务特定的 Example&#xff0c;大部分优秀的 Prompt 都需要 Example&#xff0c;这其实应用了模型的短期学习能力。另外…

自动驾驶控制算法-横向控制与流程代码仿真

本文是学习自动驾驶控制算法第八讲(一&#xff09;横向控制算法与流程图以及后续两节的学习笔记。 1 1. 算法流程图 2 A&#xff0c;B计算模块 A [ 0 1 0 0 0 C α f C α r m v x − C α f C α r m a C α f − b C α r m v x 0 0 0 1 0 a C α f − b C α r I v x −…

C++中的类型转换

类型转换 概述&#xff1a; 将一个类型显式地转换为另一个类型的过程 C风格的强制转换&#xff1a; double pi 3.14; int iPi (int)pi;不安全性&#xff1a;可能会导致一些隐式转换被执行&#xff0c;转换失败没有明显的错误提示不推荐 static_cast&#xff08;静态转换&…

Junit如何禁用指定测试类,及使用场景

在JUnit中禁用指定测试类可以通过多种方式实现&#xff0c;具体取决于使用的JUnit版本&#xff08;JUnit 4 或 JUnit 5&#xff09;。以下是针对两个版本的详细说明以及它们可能的使用场景&#xff1a; JUnit 4 禁用整个测试类 可以使用Ignore注解来忽略整个测试类。这将导致…

前端实现PDF预览的几种选择(pdfjs-dist、react-pdf、pdf-viewer)

记录 PDF预览的选型 对于浏览器自带的PDF预览 如果能直接使用&#xff0c;那自然最好不过了&#xff0c;但考虑多种因素&#xff0c;比如权限问题&#xff0c;禁止用户去下载PDF、预览样式不统一&#xff08;不同浏览器PDF预览的实现不同&#xff09;&#xff0c;所有最终放弃…

HuaWei、NVIDIA 数据中心 AI 算力对比

HuaWei Ascend 910B Ascend 910B 是 HuaWei 于 2023 年推出的高性能 AI 处理器芯片&#xff0c;其对标产品为 Nvidia A100/A800&#xff0c;其算力表现如下&#xff1a; 峰值算力&#xff1a;Ascend 910B 的半精度&#xff08;FP16&#xff09;算力达到 256 TFLOPS&#xff08;…