MyBatis-Plus 中使用 Wrapper 自定义 SQL

在 MyBatis-Plus 中使用 Wrapper 自定义 SQL 可以灵活组合条件并复用条件逻辑,通过 ${ew.customSqlSegment} 占位符注入 Wrapper 生成的 SQL 片段。以下是详细步骤和示例:

核心步骤

  1. Mapper 接口定义方法 使用 @Param("ew") 注解声明 Wrapper 参数,在 SQL 中通过 ${ew.customSqlSegment} 引用条件。

  2. XML 或注解编写 SQL 在 SQL 中嵌入 ${ew.customSqlSegment},MyBatis-Plus 会自动替换为 Wrapper 生成的 WHERE 语句(包含 WHERE 关键字)。

  3. Wrapper 构建条件 使用 QueryWrapper/LambdaQueryWrapper 组装条件,注意字段名与 SQL 中的别名一致。

示例一:XML 方式实现自定义 SQL

1. Mapper 接口声明
复制代码
java 复制代码
public interface UserMapper extends BaseMapper<User> {
    // 使用 @Param("ew") 定义 Wrapper 参数
    List<User> selectUserList(@Param("ew") Wrapper<User> wrapper);
}
2. XML 映射文件(如 UserMapper.xml
复制代码
java 复制代码
<select id="selectUserList" resultType="User">
    SELECT id, name, age, email 
    FROM user 
    ${ew.customSqlSegment} <!-- 自动注入 WHERE 及条件 -->
</select>
3. 使用 Wrapper 构建查询
复制代码
java 复制代码
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name", "张")       // 模糊查询 name 包含"张"
       .gt("age", 20)            // age > 20
       .orderByDesc("create_time"); // 按创建时间倒序

List<User> users = userMapper.selectUserList(wrapper);

生成的 SQL:

复制代码
java 复制代码
SELECT id, name, age, email 
FROM user 
WHERE name LIKE '%张%' AND age > 20 
ORDER BY create_time DESC

示例二:注解方式实现自定义 SQL

Mapper 接口直接写 SQL
复制代码
java 复制代码
@Select("SELECT * FROM user ${ew.customSqlSegment}")
List<User> selectByWrapper(@Param("ew") Wrapper<User> wrapper);

示例三:联表查询 + Wrapper

1. Mapper 接口
复制代码
java 复制代码
List<UserVO> selectUserWithRole(@Param("ew") Wrapper<User> wrapper);
2. XML 映射文件
复制代码
java 复制代码
<select id="selectUserWithRole" resultType="UserVO">
    SELECT u.*, r.role_name 
    FROM user u
    LEFT JOIN role r ON u.role_id = r.id
    ${ew.customSqlSegment} <!-- 注入条件 -->
</select>
3. 使用 LambdaWrapper(避免硬编码字段名)
复制代码
java 复制代码
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(User::getName, "王")     // 使用实体类方法引用
       .eq(User::getStatus, 1)        // status = 1
       .nested(i -> i.gt(User::getAge, 18).or().isNotNull(User::getEmail)); // 嵌套条件

List<UserVO> list = userMapper.selectUserWithRole(wrapper);

生成的 SQL:

复制代码
java 复制代码
SELECT u.*, r.role_name 
FROM user u 
LEFT JOIN role r ON u.role_id = r.id 
WHERE (
    name LIKE '%王%' 
    AND status = 1 
    AND (age > 18 OR email IS NOT NULL)
)

注意事项

  1. 防止 SQL 注入 ${ew.customSqlSegment} 内部使用预编译安全处理,但避免在 SQL 中直接拼接 ${xxx}(除 MyBatis-Plus 官方占位符外)。

  2. 表别名问题 若 SQL 中使用别名(如 u.name),Wrapper 条件需同步声明别名:

复制代码
sql 复制代码
   wrapper.like("u.name", "张"); // XML 中表别名为 u
  1. 空 Wrapper 处理 若 Wrapper 无条件,${ew.customSqlSegment} 生成空字符串,SQL 仍合法。

  2. 复杂 SQL 场景 如需分组、聚合函数等,直接在 SQL 中编写,Wrapper 仅负责 WHERE 条件部分。

总结

  • 核心占位符${ew.customSqlSegment} 注入动态条件。
  • 条件构造 :通过 QueryWrapperLambdaWrapper 构建树状条件(支持 and/or 嵌套)。
  • 安全机制:MyBatis-Plus 自动处理参数预编译,防止注入风险。

此方案完美契合 MyBatis-Plus 设计哲学,在保留原生 MyBatis 灵活性的同时,极大简化动态 SQL 编写。

相关推荐
2601_96218196几秒前
数据库之PostgreSQL详解
数据库·postgresql
天天喝旺仔4 分钟前
Docker 镜像瘦身实战:多阶段构建把体积缩小 90%
运维·后端·ci/cd·docker·云原生·容器·性能优化
疯狂打码的少年5 分钟前
【数据库技术】SQL概述与数据定义(DDL:CREATE/DROP/ALTER)
数据库·笔记·sql·oracle
Lost of 程序猿9 分钟前
ASP.NET Core Saga 分布式事务深度实战:备件采购跨服务长流程,如何保证“要么全成,要么全回“
分布式·后端·asp.net
zzzll111110 分钟前
LangChain4j:Java 生态的 AI 应用开发利器
java·开发语言·人工智能
卷无止境11 分钟前
Coding Agent 里的上下文 Compact,到底在压缩什么
后端·python
数据库小学妹18 分钟前
关系型数据库内置图查询来了:SQL/PGQ标准怎么用
数据库·图数据库·关系型数据库·图查询·数据库新特性
2601_9620710022 分钟前
【Java EE】SpringBoot的创建与简单使用
spring boot·后端·java-ee
2601_9673387129 分钟前
尚硅谷2026尚硅谷Java全栈+Python智能体教程
java·人工智能
pnoker36 分钟前
IoT DC3 时序存储选型:四款数据库可插拔
数据库·物联网·postgresql·时序数据库·influxdb·tdengine·iotdb