MyBatis 动态 SQL 的生成原理

MyBatis 动态 SQL 的生成原理主要基于其灵活的 XML 配置解析机制动态标签的递归处理逻辑,通过以下核心步骤实现 SQL 的动态拼接:


1. XML 配置解析

当 MyBatis 初始化时,会通过 XPath 解析器加载 Mapper XML 文件,提取 <select><insert> 等标签中的 SQL 语句。对于动态 SQL 标签(如 <if><choose><foreach>),MyBatis 会将其转换为特定的 SqlNode 对象,构建一个动态 SQL 节点树


2. 动态标签的 SqlNode 实现

每个动态标签对应一个 SqlNode 接口的实现类,例如:

  • <if>IfSqlNode
  • <choose>ChooseSqlNode
  • <foreach>ForEachSqlNode
  • <where>WhereSqlNode

这些 SqlNode 对象在解析时会被组织成树形结构,用于后续的动态拼接。


3. OGNL(Object-Graph Navigation Language)表达式求值

动态标签中的 test 属性(如 <if test="name != null">)使用 OGNL(对象图导航语言) 表达式进行条件判断。MyBatis 在运行时:

  1. 从参数对象中提取属性值。
  2. 通过 OgnlCache 缓存解析表达式,提高性能。
  3. 根据表达式结果(true/false)决定是否包含该 SQL 片段。

4. SQL 动态拼接过程

当执行 Mapper 方法时,MyBatis 会:

  1. 生成 SqlSource 对象:根据 XML 配置构建 DynamicSqlSource,封装动态 SQL 节点树。
  2. 获取 BoundSql 对象
    • 遍历 SqlNode 树,递归处理每个节点。
    • <if> 节点:判断条件,决定是否拼接子节点 SQL。
    • <foreach> 节点:遍历集合,展开成 IN 子句或批量插入语句。
    • <where> 节点:自动处理 WHERE 关键字和条件前的 AND/OR
  3. 参数替换:将 #{} 占位符替换为 ?,并生成 ParameterMapping 对象,记录参数位置和类型。

5. 缓存机制

MyBatis 对解析后的 SqlSourceBoundSql 进行缓存,避免重复解析 XML。首次执行时生成并缓存,后续直接复用,提升性能。


示例:动态 SQL 生成流程

假设有以下 XML 配置:

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

生成过程

  1. 解析 <where> 标签为 WhereSqlNode,内部包含两个 IfSqlNode
  2. 执行时,若 nameage 均非空:
    • WhereSqlNode 自动添加 WHERE 关键字。
    • 两个 <if> 条件成立,拼接 AND name = ? AND age = ?
    • 最终 SQL:SELECT * FROM user WHERE name = ? AND age = ?
  3. age 为空,则拼接为:SELECT * FROM user WHERE name = ?

关键设计思想

  • 组合模式:通过 SqlNode 树形结构实现动态 SQL 的灵活组合。
  • 责任链模式:每个 SqlNode 依次处理 SQL 片段,决定是否包含或跳过。
  • 表达式语言:利用 OGNL 实现简洁的条件判断。

性能优化

  • 预编译:动态 SQL 最终生成带占位符的 SQL,由 JDBC 预编译执行,防止 SQL 注入。
  • 缓存:减少 XML 解析和表达式求值次数。

通过以上机制,MyBatis 实现了高效、灵活的动态 SQL 生成,适应复杂多变的查询场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值