MyBatis-Plus 中 的动态SQL 片段(sqlSegment)详解

 更新时间:2025年06月30日 14:33:58   作者:codingPower  
MyBatis-Plus的sqlSegment通过Wrapper动态生成SQL片段,支持XML中${ew.customSqlSegment}引用,结合Lambda表达式避免硬编码,适用于动态查询、逻辑删除等场景,提升代码可维护性与灵活性,本文给大家介绍MyBatis-Plus中的动态SQL片段(sqlSegment)讲解,感兴趣的朋友一起看看吧

以下是针对 MyBatis-Plus 中 通用 SQL 片段(sqlSegment) 的清晰详解,结合核心功能与实用场景,逐步说明其用法:

一、什么是sqlSegment?

在 MyBatis-Plus 中,sqlSegment 通常指 动态生成的 SQL 代码块,例如由条件构造器(Wrapper)自动生成的 WHERE 条件、ORDER BY 排序等。开发者可通过特定语法(如 ${ew.customSqlSegment}或者${ew.sqlSegment})将这些片段插入到自定义 SQL 中,实现灵活组合。

二、核心使用方式

1.条件构造器(Wrapper)动态生成 SQL 片段

通过 QueryWrapperLambdaQueryWrapper 构建条件,自动生成 WHERE 后的条件语句。

// 创建 Wrapper
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("status", 1)
       .like("username", "Tom")
       .orderByDesc("create_time");
// 执行查询(自动拼接条件到 SQL)
List<User> users = userMapper.selectList(wrapper);

生成 SQL

SELECT * FROM user 
WHERE status = 1 AND username LIKE '%Tom%' 
ORDER BY create_time DESC

2.在 XML 中引用 Wrapper 的 SQL 片段

使用 ${ew.customSqlSegment} 占位符,将 Wrapper 中的条件插入到自定义 SQL。

<!-- XML 映射文件 -->
<select id="selectByWrapper" resultType="User">
    SELECT * FROM user
    WHERE age > 18
    ${ew.customSqlSegment}  <!-- 插入 Wrapper 的条件 -->
</select>

Java 调用

QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.ne("email", null);  // 添加条件:email IS NOT NULL
List<User> users = userMapper.selectByWrapper(wrapper);

生成 SQL

SELECT * FROM user
WHERE age > 18
  AND email IS NOT NULL  <!-- 来自 Wrapper -->

三、关键语法解析

1.${ew.customSqlSegment}的作用

  • ew 是 MyBatis-Plus 的固定参数名,代表 Wrapper 对象。
  • customSqlSegmentWrapper 中生成的 SQL 片段(如 WHERE 条件、ORDER BY)。
  • 注意:必须确保 Wrapper 对象作为参数传递到 XML 中(通常参数名为 ew)。

2.Lambda 表达式避免硬编码字段名

使用 LambdaQueryWrapper 提升代码安全性和可读性:

LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.eq(User::getStatus, 1)         // 方法引用代替字符串
             .ge(User::getAge, 18)
             .orderByAsc(User::getCreateTime);

3.${ew.customSqlSegment} 与 ${ew.sqlSegment} 的区别对比

‌1.${ew.customSqlSegment}‌:‌动态拼接完整 WHERE 条件‌:常用于无需手动编写 WHERE 的自定义 SQL 中

2.‌${ew.sqlSegment}‌:‌仅注入条件表达式‌:需手动拼接 WHERE,适用于需要精确控制 SQL 结构的场景

// Mapper 接口  
@Select("SELECT * FROM user ${ew.customSqlSegment}")  
List<User> selectPageCustom(@Param(Constants.WRAPPER) Wrapper<User> wrapper);  
@Select("SELECT * FROM user WHERE ${ew.sqlSegment}")  
List<User> selectPageWhere(@Param(Constants.WRAPPER) Wrapper<User> wrapper);  

四、实际应用场景

场景 1:动态条件查询

根据用户输入动态拼接查询条件,无需手动编写 if 判断。

public List<User> searchUsers(String name, Integer minAge) {
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    wrapper.like(StringUtils.isNotBlank(name), User::getUsername, name)
           .ge(minAge != null, User::getAge, minAge);
    return userMapper.selectList(wrapper);
}
  • likege 方法中的第一个参数为条件布尔值,自动决定是否拼接该条件。

场景 2:复用公共 SQL 片段

在 XML 中定义公共片段,结合 Wrapper 实现复用。

<!-- 定义公共的 WHERE 条件 -->
<sql id="activeUser">
    is_deleted = 0 AND status = 'ACTIVE'
</sql>
<!-- 在查询中复用 -->
<select id="selectActiveUsers" resultType="User">
    SELECT * FROM user
    WHERE <include refid="activeUser"/>
    ${ew.customSqlSegment}  <!-- 追加其他动态条件 -->
</select>

Java 调用

QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("username", "Admin");
List<User> users = userMapper.selectActiveUsers(wrapper);

生成 SQL

SELECT * FROM user
WHERE is_deleted = 0 AND status = 'ACTIVE'  <!-- 公共片段 -->
  AND username LIKE '%Admin%'              <!-- 动态条件 -->

场景 3:逻辑删除自动过滤

配置 MyBatis-Plus 全局逻辑删除,自动在所有查询中注入 WHERE is_deleted=0

# application.yml
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: isDeleted   # 实体类字段名
      logic-delete-value: 1           # 删除后的值
      logic-not-delete-value: 0       # 未删除的值
  • 无需手动编写条件,删除操作自动变为 UPDATE 语句,查询自动过滤已删除数据。

五、最佳实践与避坑指南

1.优先使用 LambdaQueryWrapper

  • 优势:避免字段名硬编码,编译时检查,重构友好。
  • 示例
    lambdaWrapper.eq(User::getStatus, 1)  // 正确性由编译器保证

2.谨慎使用${}防止 SQL 注入

  • 安全写法
    WHERE username = #{param}    <!-- 使用 #{} 预编译 -->
  • 风险写法
    ORDER BY ${orderBy}          <!-- 直接拼接字符串,需手动过滤参数 -->

3.复杂 SQL 结合 XML 片段

对于多表 JOIN 或复杂统计,仍可在 XML 中编写完整 SQL,利用 <include> 复用片段。

<select id="selectUserWithRole" resultType="map">
    SELECT u.*, r.role_name 
    FROM user u
    LEFT JOIN role r ON u.role_id = r.id
    ${ew.customSqlSegment}
</select>

六、总结

  • 核心机制:通过 Wrapper 生成动态 SQL 片段,结合 ${ew.customSqlSegment} 嵌入自定义 SQL。
  • 适用场景:动态条件查询、逻辑删除、多租户隔离、公共代码复用。
  • 优势:减少重复代码、提升可维护性、保持 SQL 灵活性。

通过合理利用 MyBatis-Plus 的 SQL 片段功能,可显著简化开发流程,尤其适合快速迭代的中大型项目。

到此这篇关于MyBatis-Plus 中 的动态SQL 片段(sqlSegment)讲解的文章就介绍到这了,更多相关MyBatis-Plus动态SQL内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot原生组件注入实现两种方式介绍

    SpringBoot原生组件注入实现两种方式介绍

    SpringBoot是Spring全家桶的成员之一,基于约定优于配置的思想(即有约定默认值,在不配置的情况下会使用默认值,在配置文件下配置的话会使用配置的值)。SpringBoot是一种整合Spring技术栈的方式(或者说是框架),同时也是简化Spring的一种快速开发的脚手架
    2022-10-10
  • SpringBoot通过JSON传递请求参数的实例详解

    SpringBoot通过JSON传递请求参数的实例详解

    这篇文章主要介绍了SpringBoot通过JSON传递请求参数,示例介绍SpringMVC如何通过JSON格式传递入参,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-11-11
  • java中全排列的生成算法汇总

    java中全排列的生成算法汇总

    本文给大家汇总介绍了常见的6种全排列的生成算法,包括字典序法、递增进位数制法、递减进位数制法、邻位交换法、递归类算法、元素增值法,有需要的小伙伴可以参考下
    2015-07-07
  • Java基础类学习之String详解

    Java基础类学习之String详解

    这篇文章主要为大家详细介绍了Java基础类中String的相关知识,文中的示例代码讲解详细,对我们学习Java有一定的帮助,需要的可以参考一下
    2022-12-12
  • 关于SpringBoot大文件RestTemplate下载解决方案

    关于SpringBoot大文件RestTemplate下载解决方案

    这篇文章主要介绍了SpringBoot大文件RestTemplate下载解决方案,最近结合网上案例及自己总结,写了一个分片下载tuling/fileServer项目,需要的朋友可以参考下
    2021-10-10
  • java集合类arraylist循环中删除特定元素的方法

    java集合类arraylist循环中删除特定元素的方法

    下面小编就为大家带来一篇Java集合类ArrayList循环中删除特定元素的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • MyBatis+MyBatisPlus中遇到的一些坑及解决

    MyBatis+MyBatisPlus中遇到的一些坑及解决

    这篇文章主要介绍了MyBatis+MyBatisPlus中遇到的一些坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • java 简单的计算器程序实例代码

    java 简单的计算器程序实例代码

    这篇文章主要介绍了java 简单的计算器程序实例代码的相关资料,需要的朋友可以参考下
    2017-06-06
  • JavaWeb开发实现备忘录

    JavaWeb开发实现备忘录

    这篇文章主要为大家详细介绍了JavaWeb开发实现备忘录,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • java中的Supplier接口解析

    java中的Supplier接口解析

    Java 8引入的Supplier接口是一个无参数函数式接口,通过get()方法延迟计算结果,它适用于按需生成场景,下面就来介绍一下如何使用,感兴趣的可以了解一下
    2025-12-12

最新评论