關鍵詞:MyBatis-Plus、QueryWrapper、動態 SQL、Java、ORM
一、引言
在 Java 后端開發中,MyBatis-Plus(簡稱 MP)作為 MyBatis 的增強工具,極大地簡化了 CRUD 操作。而其中最核心的功能之一,就是動態 SQL 的條件構造器 —— QueryWrapper
。
你是否還在手寫 XML 中的 <if test="...">
?是否還在為拼接 SQL 條件而煩惱?QueryWrapper
將帶你告別這些痛苦。
二、什么是 QueryWrapper?
QueryWrapper
是 MyBatis-Plus 提供的條件構造器,用于構建 WHERE
子句的查詢條件。它通過鏈式調用的方式,實現了類型安全、可讀性強、可復用的 SQL 構造。
類圖關系(簡化)
QueryWrapper ← AbstractWrapper ← Wrapper
Wrapper
:抽象根類,定義了條件構造的基本能力。AbstractWrapper
:封裝了條件拼接邏輯。QueryWrapper
:專用于查詢操作,支持SELECT ... WHERE ...
。
三、快速入門
1. 引入依賴
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.5</version>
</dependency>
2. 實體類
@Data
@TableName("user")
public class User {private Long id;private String name;private Integer age;private String email;
}
3. Mapper 接口
public interface UserMapper extends BaseMapper<User> {}
4. 使用 QueryWrapper 查詢
@Autowired
private UserMapper userMapper;public List<User> getUsers(String name, Integer minAge) {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.like(StringUtils.isNotBlank(name), "name", name).ge(minAge != null, "age", minAge);return userMapper.selectList(wrapper);
}
四、核心方法詳解
方法名 | 說明 | 示例 |
---|---|---|
eq | 等于 | eq("age", 20) → age = 20 |
ne | 不等于 | ne("age", 20) → age <> 20 |
gt / ge | 大于 / 大于等于 | gt("age", 18) → age > 18 |
lt / le | 小于 / 小于等于 | lt("age", 30) → age < 30 |
like | 模糊查詢 | like("name", "張") → name LIKE '%張%' |
in | 包含 | in("id", 1, 2, 3) → id IN (1,2,3) |
isNull / isNotNull | 空值判斷 | isNull("email") → email IS NULL |
orderByAsc / orderByDesc | 排序 | orderByDesc("create_time") |
五、進階用法
1. 條件優先級(括號控制)
wrapper.and(w -> w.eq("age", 20).or().eq("name", "Tom")).eq("status", 1);
生成的 SQL:
WHERE (age = 20 OR name = 'Tom') AND status = 1
2. 只查詢部分字段
wrapper.select("id", "name").eq("age", 25);
3. 排除字段
wrapper.select(User.class, info -> !info.getColumn().equals("password")).eq("status", 1);
六、實戰案例:分頁 + 多條件搜索
public IPage<User> searchUsers(String name, Integer minAge, Integer maxAge, int current, int size) {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.like(StringUtils.isNotBlank(name), "name", name).ge(minAge != null, "age", minAge).le(maxAge != null, "age", maxAge).orderByDesc("create_time");Page<User> page = new Page<>(current, size);return userMapper.selectPage(page, wrapper);
}
七、常見誤區與注意事項
誤區 | 正確做法 |
---|---|
直接拼接字段名 | 使用 LambdaQueryWrapper 避免硬編碼 |
忽略空值判斷 | 使用帶 condition 參數的重載方法 |
濫用 or() | 使用 and(Consumer<Wrapper>) 明確優先級 |
忽略 SQL 注入 | 不要手動拼接字符串,使用 MP 提供的 API |
八、LambdaQueryWrapper:類型安全升級版
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(StringUtils.isNotBlank(name), User::getName, name).ge(minAge != null, User::getAge, minAge);
優點:
- 編譯期檢查字段名
- 避免魔法字符串
- 支持方法引用
九、總結
特性 | 描述 |
---|---|
簡潔 | 鏈式調用,告別 XML |
靈活 | 動態條件,支持復雜邏輯 |
安全 | 防止 SQL 注入 |
可維護 | 與實體類聯動,易于重構 |
建議:
- 簡單查詢用
QueryWrapper
- 生產環境優先使用
LambdaQueryWrapper
- 復雜 SQL 仍可用 XML 或
@Select
十、參考資料
- MyBatis-Plus 官方文檔
- GitHub:baomidou/mybatis-plus
- 《MyBatis-Plus 實戰》