Skip to content

查询构建器


MyBatis-Plus Wrapper 体系

MyBatis-Plus 提供了一套完整的条件封装,对应 PHP 中 DB::table()->where()->orderBy()->get() 的链式调用。

条件筛选

java
// === 比较操作 ===
wrapper.eq("name", "foo");                // =     where name = 'foo'
wrapper.ne("name", "foo");                // !=    where name != 'foo'
wrapper.gt("age", 18);                    // >     where age > 18
wrapper.ge("age", 18);                    // >=    where age >= 18
wrapper.lt("age", 30);                    // <     where age < 30
wrapper.le("age", 30);                    // <=    where age <= 30

// === 模糊查询 ===
wrapper.like("name", "张");               // LIKE     where name like '%张%'
wrapper.notLike("name", "测试");          // NOT LIKE where name not like '%测试%'
wrapper.likeLeft("name", "张");           // LIKE     where name like '%张'
wrapper.likeRight("name", "张");          // LIKE     where name like '张%'

// === 范围查询 ===
wrapper.between("age", 18, 30);           // BETWEEN  where age between 18 and 30
wrapper.notBetween("age", 18, 30);        // NOT BETWEEN
wrapper.in("status", 1, 2, 3);            // IN       where status in (1,2,3)
wrapper.notIn("status", 0);               // NOT IN

// === NULL 判断 ===
wrapper.isNull("deleted_at");             // IS NULL
wrapper.isNotNull("email");               // IS NOT NULL

排序与分页

java
// 排序
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByAsc("age");                // order by age asc
wrapper.orderByDesc("created_at");        // order by created_at desc
wrapper.orderBy(true, false, "status");   // order by status desc
//                    ⬆ true=asc, false=desc

// 分页(需要 PaginationInnerInterceptor 插件)
Page<User> page = new Page<>(1, 20);      // 第1页,每页20条
Page<User> result = userMapper.selectPage(page, wrapper);

result.getRecords();      // 当前页数据 → collection
result.getTotal();        // 总记录数 → total
result.getCurrent();      // 当前页码 → current_page
result.getSize();         // 每页大小 → per_page
result.getPages();        // 总页数 → last_page

Lambda 写法(避免硬编码字段名)

java
// 字符串写法(不推荐,字段名改了不会报错)
QueryWrapper<User> w = new QueryWrapper<>();
w.eq("email", "foo@bar.com");  // 如果字段改名叫 mailbox,这里静默失效

// Lambda 写法 ✅ 推荐(编译期检查)
LambdaQueryWrapper<User> w = new LambdaQueryWrapper<>();
w.eq(User::getEmail, "foo@bar.com");   // 用方法引用,安全
w.ge(User::getAge, 18);
w.like(User::getName, "张");

逻辑组合(AND / OR)

java
// 默认是 AND
wrapper.eq("status", 1).eq("age", 18);
// → where status = 1 and age = 18

// OR
wrapper.eq("status", 1).or().eq("status", 2);
// → where status = 1 or status = 2

// 复杂嵌套(类比 Eloquent 的 where 闭包)
wrapper.and(w -> w.eq("age", 18).eq("city", "北京"))
       .or(w -> w.eq("age", 20).eq("city", "上海"));
// → where (age = 18 and city = '北京') or (age = 20 and city = '上海')

// 对应 PHP
// ->where(function($q) { $q->where('age', 18)->where('city', '北京'); })
// ->orWhere(function($q) { $q->where('age', 20)->where('city', '上海'); })

指定字段

java
// 只查询特定字段
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("id", "name", "email");

// 排除字段
wrapper.select(User.class, info -> !info.getColumn().equals("password"));

// 聚合查询
wrapper.select("count(*) as count", "status");
wrapper.groupBy("status");
// select count(*) as count, status from users group by status

⚠️ 常见坑

1. Wrapper 每次都要 new,不能复用

java
// ❌ 错误:Wrapper 有状态,不能复用
private QueryWrapper<User> baseWrapper = new QueryWrapper<>();
baseWrapper.eq("deleted", 0);

// ✅ 正确:每次查询都 new
public List<User> search(String name) {
    QueryWrapper<User> w = new QueryWrapper<>();  // 每次都新建
    w.eq("deleted", 0);
    if (name != null) w.like("name", name);
    return userMapper.selectList(w);
}

2. 条件为空时不追加

MyBatis-Plus 会自动判断:如果传入的值为 null,该条件不会追加到 SQL 中。

java
wrapper.eq(name != null, "name", name);  // 第二个参数为 boolean,控制是否加这个条件

3. 字符串字段的数字比较

java
// age 字段在数据库中是 varchar 类型
wrapper.eq("age", 18);      // → where age = '18'(自动转字符串)
// 如果传 String 给数字字段,也能工作
wrapper.eq("age", "18");    // → where age = 18(自动转数字)

4. selectOne 返回多条时抛异常

java
// 如果查询出多条记录,selectOne 会抛异常
User user = userMapper.selectOne(wrapper);  // 多条时 → TooManyResultsException

// 确实可能存在多条的情况,用 selectList 替代
List<User> users = userMapper.selectList(wrapper);

面向 PHP 开发者的 Spring Boot 文档