目录
[1. 注意事项](#1. 注意事项)
[2. 示例代码](#2. 示例代码)
[2.1 实体类](#2.1 实体类)
[2.2 Mapper 接口](#2.2 Mapper 接口)
[2.3 测试类](#2.3 测试类)
[3. 运行效果](#3. 运行效果)
[4. 总结](#4. 总结)
在实际项目中,虽然 MyBatis-Plus 提供了丰富的内置方法和 QueryWrapper
条件构造器,但有时我们需要 自定义 SQL 来实现更复杂的查询逻辑。
MyBatis-Plus 从 3.0.7 版本开始 支持 Wrapper 自定义 SQL ,结合 ${ew.customSqlSegment}
,可以在 XML 或注解中编写动态 SQL,灵活性更高。
1. 注意事项
在使用 Wrapper 自定义 SQL 时,需要注意以下几点:
-
版本要求
MyBatis-Plus 版本必须 ≥ 3.0.7 。
低版本不支持
customSqlSegment
。 -
参数命名
Wrapper 参数必须命名为
ew
,或者用
@Param(Constants.WRAPPER)
明确指定。 -
SQL 引用方式
在 SQL 语句中,使用
${ew.customSqlSegment}
引入 Wrapper 生成的 SQL 条件片段。 -
不支持基于 entity 的 where
自定义 SQL 时,Wrapper 不会基于实体类自动生成 where 条件,需要自己写 SQL。
2. 示例代码
2.1 实体类
文件:User.java
java
package com.example.pojo;
import lombok.Data;
@Data
public class User {
private Long id;
private String username;
private String info;
private Integer balance;
}
2.2 Mapper 接口
文件:UserMapper.java
java
package com.example.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.example.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface UserMapper extends BaseMapper<User> {
// 使用 Wrapper 自定义 SQL
@Select("SELECT id, username, info, balance FROM user ${ew.customSqlSegment}")
List<User> selectByCustomSql(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
2.3 测试类
文件:UserMapperTest.java
java
package com.example;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mapper.UserMapper;
import com.example.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
void testSelectByCustomSql() {
QueryWrapper<User> wrapper = new QueryWrapper<User>()
.like("username", "o") // 模糊匹配 username
.ge("balance", 1000); // balance >= 1000
List<User> users = userMapper.selectByCustomSql(wrapper);
users.forEach(System.out::println);
}
}
3. 运行效果
生成的 SQL:
sql
SELECT id, username, info, balance
FROM user
WHERE (username LIKE '%o%' AND balance >= 1000)
返回结果:
java
User(id=1, username=Tom, info=喜欢运动, balance=2000)
User(id=3, username=Bob, info=游戏达人, balance=1500)
4. 总结
-
@Select("... ${ew.customSqlSegment}")
可以结合 Wrapper 动态拼接条件,避免大量 XML 配置。 -
参数必须用
@Param(Constants.WRAPPER)
标记,或者命名为ew
。 -
灵活度比单纯
BaseMapper
的内置方法更高,适合需要部分自定义 SQL 的场景。
👉 建议在 复杂 SQL + 动态条件的场景下使用,简化 SQL 管理的同时又保留了 MyBatis-Plus 的便利性。