MyBatis-Plus 的 条件构造器详解(超详细版)

复制代码
说明:
本文内容较长,请耐心看完,看完之后你会对条件构造器有一个很深的理解。本文超详细的讲解与覆盖
MyBatis-Plus 条件改造构造器的所有方面,从基础到高级技巧,从性能优化到安全防护,你将能过更高效
,安全地构造各种复杂的SQL查询条件

为什么需要条件构造器?

一、传统SQL编写的问题

1.1 SQL注入风险高

java 复制代码
// ❌ 传统拼接SQL的写法(极度危险)
public List<User> findUsers(String name, Integer age) {
    String sql = "SELECT * FROM user WHERE 1=1";

    if (name != null) {
        sql += " AND name = '" + name + "'";  // 直接拼接,SQL注入入口!
    }
    if (age != null) {
        sql += " AND age = " + age;           // 数值型也要防注入
    }
    // 执行SQL...
}

攻击示例:

java 复制代码
-- 传入参数:name = "' OR '1'='1"
-- 最终SQL:
SELECT * FROM user WHERE 1=1 AND name = '' OR '1'='1'
-- 结果:查询出所有用户数据泄露!

1.2 代码冗余严重

java 复制代码
// ❌ 每个查询都要写重复代码
public List<User> findActiveUsers() {
    String sql = "SELECT * FROM user WHERE status = 1 AND deleted = 0";
    // 还要处理参数、异常等
}
public List<User> findUsersByDept(Long deptId) {
    String sql = "SELECT * FROM user WHERE dept_id = ? AND status = 1 AND deleted = 0";
    // 又重复了status和deleted条件
}
public List<User> findUsersByName(String name) {
    String sql = "SELECT * FROM user WHERE name LIKE ? AND status = 1 AND deleted = 0";
    // 继续重复...
}

1.3 维护成本高

java 复制代码
// 当数据库表结构变更时:
// 1. 需要找到所有使用了该表的SQL
// 2. 逐个修改字段名
// 3. 测试每个修改点

// 原始SQL:
String sql1 = "SELECT id, username, email FROM user";
String sql2 = "INSERT INTO user(username, email) VALUES(?, ?)";
String sql3 = "UPDATE user SET username = ? WHERE id = ?";
// 几十个地方需要修改...

二、条件构造器解决的痛点

2.1 解决SQL安全问题

java 复制代码
// ✅ 条件构造器自动防SQL注入
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", userInputName)    // 自动参数化:name = ?
       .gt("age", userInputAge);      // 自动参数化:age > ?

// MyBatis-Plus生成的SQL:
// SELECT * FROM user WHERE name = ? AND age > ?
// 参数:["test测试", 18]

2.2 提升开发效率

java 复制代码
// ✅ 一行代码完成复杂查询  下面会讲到每一个参数的详细解释
List<User> users = userMapper.selectList(
    new QueryWrapper<User>()
        .select("id", "name", "email", "create_time")
        .eq("status", 1)
        .ne("deleted", 1)
        .like("name", "张")
        .between("age", 18, 60)
        .in("dept_id", Arrays.asList(1, 2, 3))
        .orderByDesc("create_time")
        .last("LIMIT 100")
);

// 等价于手写:
// SELECT id, name, email, create_time 
// FROM user 
// WHERE status = 1 
//   AND deleted != 1 
//   AND name LIKE '%张%' 
//   AND age BETWEEN 18 AND 60 
//   AND dept_id IN (1,2,3) 
// ORDER BY create_time DESC 
// LIMIT 100

2.3 支持动态SQL构建

java 复制代码
// ✅ 灵活构建动态查询条件
public List<User> searchUsers(UserSearchDTO searchDTO) {
    QueryWrapper<User> wrapper = new QueryWrapper<>();

    // 根据条件动态添加
    wrapper.eq(searchDTO.getId() != null, "id", searchDTO.getId())
           .like(StringUtils.isNotBlank(searchDTO.getKeyword()), 
                 "name", searchDTO.getKeyword())
           .in(!CollectionUtils.isEmpty(searchDTO.getStatusList()),
               "status", searchDTO.getStatusList())
           .between(searchDTO.getStartDate() != null && 
                    searchDTO.getEndDate() != null,
                    "create_time", searchDTO.getStartDate(), searchDTO.getEndDate());

    // 动态排序
    if (StringUtils.isNotBlank(searchDTO.getSortField())) {
        wrapper.orderBy(true, 
                       "asc".equalsIgnoreCase(searchDTO.getSortOrder()),
                       searchDTO.getSortField());
    }

    return userMapper.selectList(wrapper);
}

2.4 实现代码复用

java 复制代码
// ✅ 基础条件封装,多处复用
public abstract class BaseQueryWrapper {

    public QueryWrapper<T> buildBaseCondition() {
        return new QueryWrapper<T>()
            .eq("is_deleted", 0)
            .eq("tenant_id", getCurrentTenantId());
    }
}

// 业务查询继承基础条件
public QueryWrapper<User> buildUserQuery(UserQuery query) {
    QueryWrapper<User> wrapper = buildBaseCondition();  // 复用基础条件

    // 添加业务特定条件
    wrapper.eq(StringUtils.isNotBlank(query.getStatus()), 
               "status", query.getStatus())
           .between(query.getStartTime() != null && query.getEndTime() != null,
                   "create_time", query.getStartTime(), query.getEndTime());

    return wrapper;
}

条件构造器解释

MyBatis-Plus 的条件构造器是其核心功能之一,用于构建复杂的 SQL 查询条件。是提高开发效率的重要特性,熟练掌握可以大幅减少 SQL 编写工作量。

复制代码
// 官网
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的
数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,
无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。

一、条件构造器体系结构

1.1 完整类继承体系

java 复制代码
Serializable
    └── Wrapper<T> (接口)
        └── AbstractWrapper<T, Children, ParamName> (抽象类)
            ├── QueryWrapper<T> extends AbstractWrapper<T, QueryWrapper<T>, String>
            ├── UpdateWrapper<T> extends AbstractWrapper<T, UpdateWrapper<T>, String>
            └── AbstractLambdaWrapper<T, Children> extends AbstractWrapper<T, Children, SFunction<T, ?>>
                ├── LambdaQueryWrapper<T> extends AbstractLambdaWrapper<T, LambdaQueryWrapper<T>>
                └── LambdaUpdateWrapper<T> extends AbstractLambdaWrapper<T, LambdaUpdateWrapper<T>>

1.2. 核心类说明

QueryWrapper

用于构建查询条件,支持所有SQL操作

核心特性:

  1. 字段名使用字符串,直接对应数据库的列名
  2. 支持复杂SQL条件构造
  3. 支持链式调用

LambdaQueryWrapper

基于Lambda表达式的类型安全查询构建器。

核心特性:

  1. 编译时类型检查,避免字段名拼写错误
  2. 编译器只能提示
  3. 支持方法应用

UpdateWrapper

用于构建更新操作的条件

核心特性:

  1. 支持SET操作
  2. 支持条件更新
  3. 支持SQL函数更新

LambdaUpdateWrapper

Lambda版本的更新条件构造器

二、条件构造器完全方法手册

  1. eq() - 等于
java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加该条件
 * column: String - 字段名
 * value: Object - 值
 * 
 * 方法重载:
 * eq(column, value)
 * eq(condition, column, value)
 * eq(lambda, value) - Lambda版本
 */
// 案例1:简单等于查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.eq("username", "zhangsan");
// SQL: SELECT * FROM user WHERE username = 'zhangsan'
// 生成的预编译SQL: SELECT * FROM user WHERE username = ?
// 参数值: ["zhangsan"]
// 案例2:多字段等于查询
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.eq("status", 1)
        .eq("deleted", 0);
// SQL: SELECT * FROM user WHERE status = 1 AND deleted = 0
// 案例3:条件判断等于查询
String searchName = "zhangsan";
QueryWrapper<User> wrapper3 = new QueryWrapper<>();
wrapper3.eq(StringUtils.isNotBlank(searchName), "username", searchName);
// 条件为true,生成SQL: SELECT * FROM user WHERE username = 'zhangsan'
String nullName = null;
wrapper3.eq(StringUtils.isNotBlank(nullName), "username", nullName);
// 条件为false,不生成该条件
// 案例4:Lambda表达式等于查询
LambdaQueryWrapper<User> lambdaWrapper1 = new LambdaQueryWrapper<>();
lambdaWrapper1.eq(User::getAge, 25);
// SQL: SELECT * FROM user WHERE age = 25
// 案例5:链式调用配合其他条件
QueryWrapper<User> wrapper5 = new QueryWrapper<>();
wrapper5.eq("type", "VIP")
        .eq("status", 1)
        .gt("balance", 1000);
// SQL: SELECT * FROM user WHERE type = 'VIP' AND status = 1 AND balance > 1000
// 案例6:复杂对象属性查询
LambdaQueryWrapper<Order> orderWrapper = new LambdaQueryWrapper<>();
orderWrapper.eq(Order::getOrderStatus, OrderStatus.PAID)
           .eq(Order::getPaymentType, PaymentType.ALIPAY);
// SQL: SELECT * FROM order WHERE order_status = 'PAID' AND payment_type = 'ALIPAY'

ne() - 不等于

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加该条件
 * column: String - 字段名
 * value: Object - 值
 */
// 案例1:简单不等于查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.ne("status", 0);
// SQL: SELECT * FROM user WHERE status != 0
// 案例2:组合不等于查询
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.eq("dept_id", 1)
        .ne("role", "admin");
// SQL: SELECT * FROM user WHERE dept_id = 1 AND role != 'admin'
// 案例3:条件判断不等于查询
Integer status = null;
QueryWrapper<User> wrapper3 = new QueryWrapper<>();
wrapper3.ne(status != null && status != 0, "status", status);
// 当status为null或0时,不生成该条件
// 案例4:Lambda表达式不等于查询
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.ne(User::getVipLevel, 0);
// SQL: SELECT * FROM user WHERE vip_level != 0
// 案例5:不等于与等于组合
QueryWrapper<Product> productWrapper = new QueryWrapper<>();
productWrapper.eq("category", "electronics")
             .ne("stock", 0)
             .ne("price", 0);
// SQL: SELECT * FROM product WHERE category = 'electronics' AND stock != 0 AND price != 0

gt() - 大于

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加该条件
 * column: String - 字段名
 * value: Object - 值
 */
// 案例1:简单大于查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.gt("age", 18);
// SQL: SELECT * FROM user WHERE age > 18
// 案例2:日期大于查询
QueryWrapper<Order> wrapper2 = new QueryWrapper<>();
wrapper2.gt("create_time", "2023-01-01 00:00:00");
// SQL: SELECT * FROM order WHERE create_time > '2023-01-01 00:00:00'
// 案例3:条件判断大于查询
Integer minPrice = 100;
QueryWrapper<Product> wrapper3 = new QueryWrapper<>();
wrapper3.gt(minPrice != null && minPrice > 0, "price", minPrice);
// 当minPrice不为null且大于0时,生成条件
// 案例4:Lambda表达式大于查询
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.gt(User::getSalary, 5000);
// SQL: SELECT * FROM user WHERE salary > 5000
// 案例5:大于与其他条件组合
QueryWrapper<Score> scoreWrapper = new QueryWrapper<>();
scoreWrapper.gt("math_score", 90)
           .gt("english_score", 85)
           .eq("exam_type", "FINAL");
// SQL: SELECT * FROM score WHERE math_score > 90 AND english_score > 85 AND exam_type = 'FINAL'

ge() - 大于等于

java 复制代码
// 案例1:简单大于等于查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.ge("score", 60);
// SQL: SELECT * FROM user WHERE score >= 60
// 案例2:时间范围查询起点
QueryWrapper<Log> wrapper2 = new QueryWrapper<>();
wrapper2.ge("operation_time", LocalDateTime.now().minusDays(7));
// SQL: SELECT * FROM log WHERE operation_time >= '2024-01-01 00:00:00'
// 案例3:Lambda表达式大于等于查询
LambdaQueryWrapper<Order> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.ge(Order::getAmount, 100.00);
// SQL: SELECT * FROM order WHERE amount >= 100.00

lt() - 小于

java 复制代码
// 案例1:简单小于查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.lt("age", 65);
// SQL: SELECT * FROM user WHERE age < 65
// 案例2:日期小于查询
QueryWrapper<Order> wrapper2 = new QueryWrapper<>();
wrapper2.lt("expire_time", LocalDateTime.now());
// SQL: SELECT * FROM order WHERE expire_time < NOW()
// 案例3:Lambda表达式小于查询
LambdaQueryWrapper<Product> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.lt(Product::getStock, 10);
// SQL: SELECT * FROM product WHERE stock < 10

le() - 小于等于

java 复制代码
// 案例1:简单小于等于查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.le("age", 18);
// SQL: SELECT * FROM user WHERE age <= 18
// 案例2:截止时间查询
QueryWrapper<Task> wrapper2 = new QueryWrapper<>();
wrapper2.le("deadline", "2023-12-31 23:59:59");
// SQL: SELECT * FROM task WHERE deadline <= '2023-12-31 23:59:59'
// 案例3:Lambda表达式小于等于查询
LambdaQueryWrapper<Salary> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.le(Salary::getBasicSalary, 10000);
// SQL: SELECT * FROM salary WHERE basic_salary <= 10000

between() - 区间查询

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加该条件
 * column: String - 字段名
 * value1: Object - 区间开始值
 * value2: Object - 区间结束值
 */
// 案例1:数字区间查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.between("age", 18, 30);
// SQL: SELECT * FROM user WHERE age BETWEEN 18 AND 30
// 案例2:日期区间查询
QueryWrapper<Order> wrapper2 = new QueryWrapper<>();
wrapper2.between("create_time", 
                LocalDateTime.of(2023, 1, 1, 0, 0, 0),
                LocalDateTime.of(2023, 12, 31, 23, 59, 59));
// SQL: SELECT * FROM order WHERE create_time BETWEEN '2023-01-01 00:00:00' AND '2023-12-31 23:59:59'
// 案例3:价格区间查询
QueryWrapper<Product> wrapper3 = new QueryWrapper<>();
BigDecimal minPrice = new BigDecimal("100.00");
BigDecimal maxPrice = new BigDecimal("1000.00");
wrapper3.between("price", minPrice, maxPrice);
// SQL: SELECT * FROM product WHERE price BETWEEN 100.00 AND 1000.00
// 案例4:条件判断区间查询
LocalDateTime startTime = getStartTime();
LocalDateTime endTime = getEndTime();
QueryWrapper<Log> wrapper4 = new QueryWrapper<>();
wrapper4.between(startTime != null && endTime != null, 
                "log_time", startTime, endTime);
// 当startTime和endTime都不为null时,生成区间条件
// 案例5:Lambda表达式区间查询
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.between(User::getCreateTime, 
                     LocalDate.now().minusDays(7).atStartOfDay(),
                     LocalDateTime.now());
// SQL: SELECT * FROM user WHERE create_time BETWEEN '2024-01-01 00:00:00' AND NOW()

notBetween() - 不在区间内

java 复制代码
// 案例1:数字不在区间内查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.notBetween("age", 18, 30);
// SQL: SELECT * FROM user WHERE age NOT BETWEEN 18 AND 30
// 案例2:日期不在区间内查询
QueryWrapper<Order> wrapper2 = new QueryWrapper<>();
wrapper2.notBetween("create_time", 
                   "2023-01-01", 
                   "2023-12-31");
// SQL: SELECT * FROM order WHERE create_time NOT BETWEEN '2023-01-01' AND '2023-12-31'
// 案例3:Lambda表达式不在区间内查询
LambdaQueryWrapper<Product> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.notBetween(Product::getPrice, 
                        new BigDecimal("50.00"), 
                        new BigDecimal("200.00"));
// SQL: SELECT * FROM product WHERE price NOT BETWEEN 50.00 AND 200.00

** like() - 全模糊匹配**

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加该条件
 * column: String - 字段名
 * value: Object - 值(自动添加%)
 */
// 案例1:简单模糊查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.like("username", "张");
// SQL: SELECT * FROM user WHERE username LIKE '%张%'
// 案例2:多个模糊条件
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.like("name", "王")
        .like("email", "qq.com");
// SQL: SELECT * FROM user WHERE name LIKE '%王%' AND email LIKE '%qq.com%'
// 案例3:条件判断模糊查询
String keyword = "test";
QueryWrapper<Product> wrapper3 = new QueryWrapper<>();
wrapper3.like(StringUtils.isNotBlank(keyword), "product_name", keyword);
// 当keyword不为空时,生成模糊查询条件
// 案例4:Lambda表达式模糊查询
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.like(User::getAddress, "北京");
// SQL: SELECT * FROM user WHERE address LIKE '%北京%'
// 案例5:转义特殊字符查询
QueryWrapper<User> wrapper5 = new QueryWrapper<>();
wrapper5.like("name", "张_", SqlLike.DEFAULT);
// SQL: SELECT * FROM user WHERE name LIKE '%张\_%'

notLike() - 不包含

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加该条件
 * column: String - 字段名
 * value: Object - 值(自动在左侧添加%)
 */
// 案例1:后缀匹配查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.likeLeft("mobile", "8888");
// SQL: SELECT * FROM user WHERE mobile LIKE '%8888'
// 案例2:Lambda表达式左模糊查询
LambdaQueryWrapper<Product> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.likeLeft(Product::getSku, "001");
// SQL: SELECT * FROM product WHERE sku LIKE '%001'
// 案例3:用于编码后缀查询
QueryWrapper<Order> wrapper3 = new QueryWrapper<>();
wrapper3.likeLeft("order_no", "202312");
// 查询所有以202312结尾的订单号

likeRight() - 右模糊匹配

java 复制代码
// 案例1:前缀匹配查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.likeRight("username", "zhang");
// SQL: SELECT * FROM user WHERE username LIKE 'zhang%'
// 案例2:Lambda表达式右模糊查询
LambdaQueryWrapper<File> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.likeRight(File::getFileName, "report_");
// SQL: SELECT * FROM file WHERE file_name LIKE 'report_%'
// 案例3:用于编码前缀查询
QueryWrapper<Order> wrapper3 = new QueryWrapper<>();
wrapper3.likeRight("order_no", "ORDER2023");
// 查询所有以ORDER2023开头的订单号

isNull() - 为空

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加该条件
 * column: String - 字段名
 */
// 案例1:简单空值查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.isNull("email");
// SQL: SELECT * FROM user WHERE email IS NULL
// 案例2:多字段为空查询
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.isNull("last_login_time")
        .isNull("last_login_ip");
// SQL: SELECT * FROM user WHERE last_login_time IS NULL AND last_login_ip IS NULL
// 案例3:条件判断空值查询
boolean checkNull = true;
QueryWrapper<User> wrapper3 = new QueryWrapper<>();
wrapper3.isNull(checkNull, "avatar");
// 当checkNull为true时,生成条件
// 案例4:Lambda表达式空值查询
LambdaQueryWrapper<Order> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.isNull(Order::getDeliveryTime);
// SQL: SELECT * FROM order WHERE delivery_time IS NULL
// 案例5:空值与其他条件组合
QueryWrapper<Task> taskWrapper = new QueryWrapper<>();
taskWrapper.eq("status", "PENDING")
          .isNull("assignee_id");
// SQL: SELECT * FROM task WHERE status = 'PENDING' AND assignee_id IS NULL

isNotNull() - 不为空

java 复制代码
// 案例1:简单非空查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.isNotNull("phone");
// SQL: SELECT * FROM user WHERE phone IS NOT NULL
// 案例2:Lambda表达式非空查询
LambdaQueryWrapper<Employee> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.isNotNull(Employee::getDepartment);
// SQL: SELECT * FROM employee WHERE department IS NOT NULL
// 案例3:非空与条件组合
QueryWrapper<Article> articleWrapper = new QueryWrapper<>();
articleWrapper.isNotNull("content")
             .isNotNull("title")
             .eq("status", "PUBLISHED");
// SQL: SELECT * FROM article WHERE content IS NOT NULL AND title IS NOT NULL AND status = 'PUBLISHE

in() - 包含在集合中

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加该条件
 * column: String - 字段名
 * value: Collection<?> - 值集合
 * 或 values: Object... - 可变参数
 */
// 案例1:集合方式IN查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
List<Integer> statusList = Arrays.asList(1, 2, 3);
wrapper1.in("status", statusList);
// SQL: SELECT * FROM user WHERE status IN (1, 2, 3)
// 案例2:数组方式IN查询
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.in("dept_id", 1, 2, 3, 4);
// SQL: SELECT * FROM user WHERE dept_id IN (1, 2, 3, 4)
// 案例3:字符串数组IN查询
QueryWrapper<Product> wrapper3 = new QueryWrapper<>();
wrapper3.in("category", "电子产品", "服装", "食品");
// SQL: SELECT * FROM product WHERE category IN ('电子产品', '服装', '食品')
// 案例4:条件判断IN查询
List<Long> userIds = getUserIds();
QueryWrapper<Order> wrapper4 = new QueryWrapper<>();
wrapper4.in(userIds != null && !userIds.isEmpty(), "user_id", userIds);
// 当userIds不为空时,生成IN条件
// 案例5:Lambda表达式IN查询
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
List<String> roles = Arrays.asList("admin", "editor");
lambdaWrapper.in(User::getRole, roles);
// SQL: SELECT * FROM user WHERE role IN ('admin', 'editor')
// 案例6:多字段IN查询
QueryWrapper<User> wrapper6 = new QueryWrapper<>();
wrapper6.in("id", Arrays.asList(1, 2, 3))
        .in("status", Arrays.asList(0, 1));
// SQL: SELECT * FROM user WHERE id IN (1, 2, 3) AND status IN (0, 1)
// 案例7:空集合处理
List<String> emptyList = Collections.emptyList();
QueryWrapper<User> wrapper7 = new QueryWrapper<>();
wrapper7.in("id", emptyList);
// MyBatis-Plus 3.x+ 自动处理空集合,不会生成IN条件

notIn() - 不包含在集合中

java 复制代码
// 案例1:集合方式NOT IN查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
List<Integer> excludeStatus = Arrays.asList(0, 9);
wrapper1.notIn("status", excludeStatus);
// SQL: SELECT * FROM user WHERE status NOT IN (0, 9)
// 案例2:数组方式NOT IN查询
QueryWrapper<Product> wrapper2 = new QueryWrapper<>();
wrapper2.notIn("product_id", 1001, 1002, 1003);
// SQL: SELECT * FROM product WHERE product_id NOT IN (1001, 1002, 1003)
// 案例3:Lambda表达式NOT IN查询
LambdaQueryWrapper<Order> lambdaWrapper = new LambdaQueryWrapper<>();
List<String> excludeTypes = Arrays.asList("TEST", "DRAFT");
lambdaWrapper.notIn(Order::getOrderType, excludeTypes);
// SQL: SELECT * FROM order WHERE order_type NOT IN ('TEST', 'DRAFT')

inSql() - SQL子查询IN

java 复制代码
**
 * 参数说明:
 * condition: boolean - 是否添加该条件
 * column: String - 字段名
 * inValue: String - SQL子查询语句
 */
// 案例1:简单子查询IN
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.inSql("dept_id", "SELECT id FROM department WHERE status = 1");
// SQL: SELECT * FROM user WHERE dept_id IN (SELECT id FROM department WHERE status = 1)
// 案例2:带参数子查询IN
QueryWrapper<Order> wrapper2 = new QueryWrapper<>();
String category = "VIP";
wrapper2.inSql("user_id", 
    "SELECT user_id FROM user_level WHERE level_name = '" + category + "'");
// 注意:要小心SQL注入,建议使用参数化
// 案例3:复杂子查询IN
QueryWrapper<Employee> wrapper3 = new QueryWrapper<>();
wrapper3.inSql("id",
    "SELECT e.id FROM employee e " +
    "JOIN department d ON e.dept_id = d.id " +
    "WHERE d.company_id = 1 AND e.status = 'ACTIVE'");
// SQL: SELECT * FROM employee WHERE id IN (SELECT e.id FROM...)
// 案例4:Lambda表达式SQL IN
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.inSql(User::getId, 
    "SELECT user_id FROM user_role WHERE role_id = 1");

notInSql() - SQL子查询NOT IN

java 复制代码
// 案例1:简单子查询NOT IN
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.notInSql("id", "SELECT user_id FROM blacklist");
// SQL: SELECT * FROM user WHERE id NOT IN (SELECT user_id FROM blacklist)
// 案例2:Lambda表达式SQL NOT IN
LambdaQueryWrapper<Order> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.notInSql(Order::getUserId,
    "SELECT id FROM user WHERE status = 0");

and() - AND连接

java 复制代码
/**
 * 参数说明:
 * consumer: Consumer<Children> - 消费者函数,构建嵌套条件
 */
// 案例1:显式AND连接
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.eq("status", 1)
        .and(w -> w.eq("type", "VIP").gt("balance", 1000));
// SQL: SELECT * FROM user WHERE status = 1 AND (type = 'VIP' AND balance > 1000)
// 案例2:复杂AND嵌套
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.eq("dept_id", 1)
        .and(w -> w.like("name", "张")
                   .or()
                   .like("name", "王"))
        .gt("age", 18);
// SQL: SELECT * FROM user WHERE dept_id = 1 AND (name LIKE '%张%' OR name LIKE '%王%') AND age > 18
// 案例3:多层级AND嵌套
QueryWrapper<Order> wrapper3 = new QueryWrapper<>();
wrapper3.eq("status", "PAID")
        .and(w -> w.between("amount", 100, 1000)
                   .and(inner -> inner.eq("payment_type", "ALIPAY")
                                       .or()
                                       .eq("payment_type", "WECHAT")));
// SQL: SELECT * FROM order WHERE status = 'PAID' AND (amount BETWEEN 100 AND 1000 AND (payment_type = 'ALIPAY' OR payment_type = 'WECHAT'))
// 案例4:AND条件分组
QueryWrapper<Product> wrapper4 = new QueryWrapper<>();
wrapper4.eq("category", "Electronics")
        .and(w -> w.gt("price", 100)
                   .lt("price", 1000)
                   .eq("in_stock", true));
// SQL: SELECT * FROM product WHERE category = 'Electronics' AND (price > 100 AND price < 1000 AND in_stock = true)

or() - OR连接

java 复制代码
/**
 * 参数说明:
 * consumer: Consumer<Children> - 消费者函数,构建嵌套条件
 */
// 案例1:简单OR连接
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.eq("status", 1)
        .or()
        .eq("status", 2);
// SQL: SELECT * FROM user WHERE status = 1 OR status = 2
// 案例2:OR嵌套条件
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.eq("dept_id", 1)
        .or(w -> w.eq("dept_id", 2).gt("level", 3));
// SQL: SELECT * FROM user WHERE dept_id = 1 OR (dept_id = 2 AND level > 3)
// 案例3:多个OR条件
QueryWrapper<Product> wrapper3 = new QueryWrapper<>();
wrapper3.eq("category", "Books")
        .or()
        .eq("category", "Music")
        .or()
        .eq("category", "Movies");
// SQL: SELECT * FROM product WHERE category = 'Books' OR category = 'Music' OR category = 'Movies'
// 案例4:OR与AND混合
QueryWrapper<User> wrapper4 = new QueryWrapper<>();
wrapper4.eq("type", "ADMIN")
        .or(w -> w.eq("type", "VIP").gt("score", 90))
        .eq("status", 1);
// SQL: SELECT * FROM user WHERE (type = 'ADMIN' OR (type = 'VIP' AND score > 90)) AND status = 1
// 案例5:复杂OR逻辑
QueryWrapper<Order> wrapper5 = new QueryWrapper<>();
wrapper5.eq("status", "PAID")
        .or(w -> w.eq("status", "SHIPPED")
                   .and(inner -> inner.isNotNull("tracking_no")
                                 .eq("shipping_company", "SF")))
        .ge("create_time", LocalDateTime.now().minusDays(30));
// SQL: SELECT * FROM order WHERE (status = 'PAID' OR (status = 'SHIPPED' AND tracking_no IS NOT NULL AND shipping_company = 'SF')) AND create_time >= ...

nested() - 嵌套条件

java 复制代码
// 案例1:嵌套条件封装
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.nested(w -> w.eq("status", 1).or().eq("status", 2))
        .gt("age", 18);
// SQL: SELECT * FROM user WHERE (status = 1 OR status = 2) AND age > 18
// 案例2:多级嵌套
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.nested(w -> w.like("name", "张")
                       .or()
                       .nested(inner -> inner.like("name", "王").eq("gender", "M")))
        .eq("dept_id", 1);
// SQL: SELECT * FROM user WHERE (name LIKE '%张%' OR (name LIKE '%王%' AND gender = 'M')) AND dept_id = 1

allEq() - 全部等于

java 复制代码
/**
 * 参数说明:
 * params: Map<String, Object> - 字段名和值的映射
 * condition: boolean - 是否添加条件
 * filter: BiPredicate<String, Object> - 过滤器函数
 * 
 * 方法重载:
 * allEq(params)
 * allEq(params, condition)
 * allEq(filter, params)
 */
// 案例1:基础全部等于查询
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
Map<String, Object> params = new HashMap<>();
params.put("status", 1);
params.put("type", "VIP");
params.put("gender", "M");
wrapper1.allEq(params);
// SQL: SELECT * FROM user WHERE status = 1 AND type = 'VIP' AND gender = 'M'
// 案例2:忽略null值
Map<String, Object> params2 = new HashMap<>();
params2.put("status", 1);
params2.put("type", null);  // null值
params2.put("gender", "M");
wrapper1.allEq(params2, false);  // 第二个参数false表示忽略null值
// SQL: SELECT * FROM user WHERE status = 1 AND gender = 'M'
// 案例3:包含null值
wrapper1.allEq(params2, true);  // true表示包含null值
// SQL: SELECT * FROM user WHERE status = 1 AND type IS NULL AND gender = 'M'
// 案例4:自定义过滤器
Map<String, Object> params3 = new HashMap<>();
params3.put("id", 1);
params3.put("name", "张三");
params3.put("password", "123456");  // 敏感字段
params3.put("email", "test@test.com");
// 过滤掉password字段
wrapper1.allEq((k, v) -> !k.equals("password"), params3);
// SQL: SELECT * FROM user WHERE id = 1 AND name = '张三' AND email = 'test@test.com'
// 案例5:复杂过滤逻辑
wrapper1.allEq((k, v) -> {
    // 过滤空字符串
    if (v instanceof String && StringUtils.isEmpty((String) v)) {
        return false;
    }
    // 过滤特定字段
    if ("internal_field".equals(k)) {
        return false;
    }
    return true;
}, params3);
// 案例6:条件判断全部等于
boolean shouldApply = true;
wrapper1.allEq(params, shouldApply);
// 当shouldApply为true时应用条件

apply() - 应用SQL片段

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加条件
 * applySql: String - SQL片段
 * values: Object... - 参数值
 */
// 案例1:简单SQL片段
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.apply("id = 1");
// SQL: SELECT * FROM user WHERE id = 1
// 案例2:带参数SQL片段
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.apply("DATE(create_time) = {0}", "2023-12-01");
// SQL: SELECT * FROM user WHERE DATE(create_time) = '2023-12-01'
// 案例3:多个参数SQL片段
QueryWrapper<User> wrapper3 = new QueryWrapper<>();
wrapper3.apply("create_time BETWEEN {0} AND {1}", 
               "2023-01-01", "2023-12-31");
// SQL: SELECT * FROM user WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'
// 案例4:函数调用
QueryWrapper<User> wrapper4 = new QueryWrapper<>();
wrapper4.apply("LOWER(name) = LOWER({0})", "ZHANGSAN");
// SQL: SELECT * FROM user WHERE LOWER(name) = LOWER('ZHANGSAN')
// 案例5:JSON查询(MySQL)
QueryWrapper<User> wrapper5 = new QueryWrapper<>();
wrapper5.apply("JSON_CONTAINS(tags, {0})", "\"VIP\"");
// SQL: SELECT * FROM user WHERE JSON_CONTAINS(tags, '"VIP"')
// 案例6:地理空间查询
QueryWrapper<Store> wrapper6 = new QueryWrapper<>();
wrapper6.apply("ST_Distance_Sphere(point({0}, {1}), point(longitude, latitude)) < {2}",
               116.404, 39.915, 5000);
// SQL: SELECT * FROM store WHERE ST_Distance_Sphere(point(116.404, 39.915), point(longitude, latitude)) < 5000
// 案例7:正则表达式
QueryWrapper<User> wrapper7 = new QueryWrapper<>();
wrapper7.apply("email REGEXP {0}", "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
// SQL: SELECT * FROM user WHERE email REGEXP '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
// 案例8:条件判断应用SQL片段
boolean useSpecialCondition = true;
wrapper1.apply(useSpecialCondition, "version = {0}", 2);

** last() - 最后拼接SQL**

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加条件
 * lastSql: String - SQL片段(会拼接到SQL最后)
 * 
 * 警告:注意SQL注入风险!
 */
// 案例1:添加LIMIT
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.eq("status", 1)
        .last("LIMIT 10");
// SQL: SELECT * FROM user WHERE status = 1 LIMIT 10
// 案例2:添加FOR UPDATE(悲观锁)
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.eq("id", 1)
        .last("FOR UPDATE");
// SQL: SELECT * FROM user WHERE id = 1 FOR UPDATE
// 案例3:MySQL分页优化
QueryWrapper<User> wrapper3 = new QueryWrapper<>();
wrapper3.eq("status", 1)
        .last("LIMIT 10000, 20");
// SQL: SELECT * FROM user WHERE status = 1 LIMIT 10000, 20
// 案例4:Oracle分页
QueryWrapper<User> wrapper4 = new QueryWrapper<>();
wrapper4.eq("status", 1)
        .last("OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY");
// SQL: SELECT * FROM user WHERE status = 1 OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY
// 案例5:SQL Server分页
QueryWrapper<User> wrapper5 = new QueryWrapper<>();
wrapper5.eq("status", 1)
        .last("OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY");
// 案例6:添加优化器提示
QueryWrapper<User> wrapper6 = new QueryWrapper<>();
wrapper6.last("/*+ INDEX(user idx_status) */")
        .eq("status", 1);
// SQL: SELECT /*+ INDEX(user idx_status) */ * FROM user WHERE status = 1
// 案例7:安全使用last(避免SQL注入)
String userInput = request.getParameter("orderBy");
// ❌ 危险
wrapper1.last("ORDER BY " + userInput);
// ✅ 安全
if ("create_time".equals(userInput) || "update_time".equals(userInput)) {
    wrapper1.last("ORDER BY " + userInput);
}

orderBy() - 排序

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否排序
 * isAsc: boolean - 是否升序
 * columns: String... - 字段名 是数据库中表的字段名
 */
// 案例1:简单排序
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.orderBy(true, true, "create_time");
// SQL: SELECT * FROM user ORDER BY create_time ASC
// 案例2:多字段排序
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.orderBy(true, true, "dept_id", "age")
        .orderBy(true, false, "salary");
// SQL: SELECT * FROM user ORDER BY dept_id ASC, age ASC, salary DESC
// 案例3:条件排序
QueryWrapper<User> wrapper3 = new QueryWrapper<>();
boolean needOrder = true;
wrapper3.orderBy(needOrder, true, "create_time");
// 当needOrder为true时排序
// 案例4:Lambda表达式排序
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.orderByAsc(User::getAge)
            .orderByDesc(User::getCreateTime);
// SQL: SELECT * FROM user ORDER BY age ASC, create_time DESC
// 案例5:复杂排序逻辑
String orderField = request.getParameter("orderField");
String orderType = request.getParameter("orderType");
QueryWrapper<User> wrapper5 = new QueryWrapper<>();
if ("age".equals(orderField)) {
    wrapper5.orderBy(true, "asc".equalsIgnoreCase(orderType), "age");
} else if ("salary".equals(orderField)) {
    wrapper5.orderBy(true, "asc".equalsIgnoreCase(orderType), "salary");
} else {
    wrapper5.orderByDesc("create_time");  // 默认排序

orderByAsc() - 升序排序

java 复制代码
// 是数据库中表的字段名
// 案例1:单字段升序
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.orderByAsc("age");
// SQL: SELECT * FROM user ORDER BY age ASC
// 案例2:多字段升序
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.orderByAsc("dept_id", "employee_id");
// SQL: SELECT * FROM user ORDER BY dept_id ASC, employee_id ASC
// 案例3:Lambda表达式升序
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.orderByAsc(User::getCreateTime);

orderByDesc() - 降序排序

java 复制代码
// 是数据库中表的字段名
// 案例1:单字段降序
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.orderByDesc("create_time");
// SQL: SELECT * FROM user ORDER BY create_time DESC
// 案例2:多字段降序
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.orderByDesc("score", "create_time");
// SQL: SELECT * FROM user ORDER BY score DESC, create_time DESC
// 案例3:混合排序
QueryWrapper<User> wrapper3 = new QueryWrapper<>();
wrapper3.orderByAsc("status")
        .orderByDesc("priority", "create_time");
// SQL: SELECT * FROM user ORDER BY status ASC, priority DESC, create_time DESC

groupBy() - 分组

java 复制代码
/**
 * 参数说明:
 * columns: String... - 分组字段
 */
// 案例1:简单分组
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.groupBy("dept_id");
// SQL: SELECT * FROM user GROUP BY dept_id
// 案例2:多字段分组
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.groupBy("dept_id", "gender");
// SQL: SELECT * FROM user GROUP BY dept_id, gender
// 案例3:分组与聚合
QueryWrapper<User> wrapper3 = new QueryWrapper<>();
wrapper3.select("dept_id", "COUNT(*) as user_count", "AVG(age) as avg_age")
        .groupBy("dept_id");
// SQL: SELECT dept_id, COUNT(*) as user_count, AVG(age) as avg_age FROM user GROUP BY dept_id
// 案例4:Lambda表达式分组
LambdaQueryWrapper<Order> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.select(Order::getProductId, 
                    "SUM(quantity) as total_quantity",
                    "SUM(amount) as total_amount")
            .groupBy(Order::getProductId);

having() - 分组后过滤

java 复制代码
/**
 * 参数说明:
 * condition: boolean - 是否添加条件
 * havingSql: String - HAVING SQL片段
 * params: Object... - 参数值
 */
// 案例1:简单HAVING条件
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.select("dept_id", "COUNT(*) as count")
        .groupBy("dept_id")
        .having("COUNT(*) > 5");
// SQL: SELECT dept_id, COUNT(*) as count FROM user GROUP BY dept_id HAVING COUNT(*) > 5
// 案例2:带参数HAVING条件
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.select("age", "AVG(salary) as avg_salary")
        .groupBy("age")
        .having("AVG(salary) > {0}", 10000);
// SQL: SELECT age, AVG(salary) as avg_salary FROM user GROUP BY age HAVING AVG(salary) > 10000
// 案例3:多个HAVING条件
QueryWrapper<User> wrapper3 = new QueryWrapper<>();
wrapper3.select("dept_id", "gender", 
                "COUNT(*) as count", 
                "AVG(age) as avg_age")
        .groupBy("dept_id", "gender")
        .having("COUNT(*) >= 3 AND AVG(age) < 40");
// SQL: SELECT dept_id, gender, COUNT(*) as count, AVG(age) as avg_age FROM user GROUP BY dept_id, gender HAVING COUNT(*) >= 3 AND AVG(age) < 40
// 案例4:复杂聚合HAVING
QueryWrapper<Order> wrapper4 = new QueryWrapper<>();
wrapper4.select("user_id", 
                "COUNT(*) as order_count",
                "SUM(amount) as total_amount",
                "MAX(amount) as max_amount")
        .groupBy("user_id")
        .having("COUNT(*) > 10 AND SUM(amount) > 10000");
// SQL: SELECT user_id, COUNT(*) as order_count, SUM(amount) as total_amount, MAX(amount) as max_amount FROM order GROUP BY user_id HAVING COUNT(*) > 10 AND SUM(amount) > 10000

select() - 选择字段

java 复制代码
/**
 * 参数说明:
 * columns: String... - 字段名
 * 或 
 * entityClass: Class<T> - 实体类
 * predicate: Predicate<TableFieldInfo> - 字段过滤器
 */
// 案例1:选择特定字段
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.select("id", "username", "email");
// SQL: SELECT id, username, email FROM user
// 案例2:选择所有字段(默认)
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
// 不调用select(),默认SELECT *
// 案例3:选择聚合字段
QueryWrapper<User> wrapper3 = new QueryWrapper<>();
wrapper3.select("COUNT(*) as user_count", 
                "AVG(age) as avg_age",
                "MAX(salary) as max_salary");
// SQL: SELECT COUNT(*) as user_count, AVG(age) as avg_age, MAX(salary) as max_salary FROM user
// 案例4:排除敏感字段
QueryWrapper<User> wrapper4 = new QueryWrapper<>();
wrapper4.select(User.class, 
    tableFieldInfo -> !tableFieldInfo.getColumn().equals("password") &&
                     !tableFieldInfo.getColumn().equals("salt"));
// SQL: 选择除了password和salt之外的所有字段
// 案例5:Lambda表达式选择字段
LambdaQueryWrapper<User> lambdaWrapper1 = new LambdaQueryWrapper<>();
lambdaWrapper1.select(User::getId, 
                     User::getUsername, 
                     User::getEmail);
// SQL: SELECT id, username, email FROM user
// 案例6:混合选择方式
QueryWrapper<User> wrapper6 = new QueryWrapper<>();
wrapper6.select("u.*", 
                "d.name as dept_name",
                "r.role_name")
        .from("user u")
        .leftJoin("department d ON u.dept_id = d.id")
        .leftJoin("user_role ur ON u.id = ur.user_id")
        .leftJoin("role r ON ur.role_id = r.id");
// SQL: SELECT u.*, d.name as dept_name, r.role_name FROM user u LEFT JOIN...
// 案例7:动态选择字段
boolean needDetail = true;
QueryWrapper<User> wrapper7 = new QueryWrapper<>();
if (needDetail) {
    wrapper7.select("id", "username", "email", "phone", "address");
} else {
    wrapper7.select("id", "username", "avatar");
}

selectMaps() - 返回Map列表

java 复制代码
// 案例:查询返回Map
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("id", "username", "age");
// 使用selectMaps方法
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
// 返回结果示例:[{id=1, username="zhangsan", age=25}, ...]
// 适用于统计查询
QueryWrapper<User> statWrapper = new QueryWrapper<>();
statWrapper.select("dept_id", 
                  "COUNT(*) as user_count",
                  "AVG(age) as avg_age")
          .groupBy("dept_id");
List<Map<String, Object>> stats = userMapper.selectMaps(statWrapper);
// 结果:[{dept_id=1, user_count=10, avg_age=28.5}, ...]

** Lambda表达式条件**

java 复制代码
// 案例1:LambdaQueryWrapper基础用法
LambdaQueryWrapper<User> lambdaWrapper = Wrappers.lambdaQuery();
// 类型安全,避免字段名错误
lambdaWrapper.eq(User::getUsername, "zhangsan")
             .gt(User::getAge, 18)
             .lt(User::getAge, 60);
// 案例2:Lambda链式调用
List<User> users = userMapper.selectList(
    new LambdaQueryWrapper<User>()
        .eq(User::getStatus, 1)
        .like(User::getUsername, "张")
        .between(User::getCreateTime,
                 LocalDateTime.now().minusDays(30),
                 LocalDateTime.now())
        .orderByDesc(User::getCreateTime)
        .last("LIMIT 100")
);
// 案例3:Lambda嵌套条件
LambdaQueryWrapper<User> nestedLambda = new LambdaQueryWrapper<>();
nestedLambda.eq(User::getDeptId, 1)
           .and(w -> w.eq(User::getRole, "ADMIN")
                      .or()
                      .gt(User::getLevel, 5));
// 案例4:Lambda选择字段
LambdaQueryWrapper<User> selectLambda = new LambdaQueryWrapper<>();
selectLambda.select(User::getId,
                   User::getUsername,
                   User::getEmail,
                   User::getCreateTime)
           .eq(User::getStatus, 1);
// 案例5:Lambda聚合查询
LambdaQueryWrapper<Order> aggLambda = new LambdaQueryWrapper<>();
aggLambda.select(Order::getProductId,
                "SUM(amount) as total_amount",
                "COUNT(*) as order_count")
        .groupBy(Order::getProductId)
        .having("COUNT(*) > 10");
// 案例6:Lambda防止空指针
String searchName = null;
LambdaQueryWrapper<User> safeLambda = new LambdaQueryWrapper<>();
safeLambda.eq(StringUtils.isNotBlank(searchName), 
             User::getUsername, searchName)
         .eq(User::getStatus, 1);
// 当searchName为null或空时,eq条件不会被添加

LambdaUpdateWrapper更新

java 复制代码
// 案例1:LambdaUpdateWrapper基础更新
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.set(User::getEmail, "new@email.com")
            .set(User::getUpdateTime, LocalDateTime.now())
            .eq(User::getId, 1);
int rows = userMapper.update(null, updateWrapper);
// 案例2:条件更新
LambdaUpdateWrapper<User> conditionalUpdate = new LambdaUpdateWrapper<>();
conditionalUpdate.set(User::getLastLoginTime, LocalDateTime.now())
                .setSql("login_count = login_count + 1")
                .eq(User::getId, userId)
                .ne(User::getEmail, "new@email.com");  // 只有邮箱不是新邮箱时才更新
// 案例3:批量更新
List<Long> userIds = Arrays.asList(1L, 2L, 3L);
LambdaUpdateWrapper<User> batchUpdate = new LambdaUpdateWrapper<>();
batchUpdate.set(User::getStatus, 0)
           .set(User::getUpdateTime, LocalDateTime.now())
           .in(User::getId, userIds)
           .eq(User::getStatus, 1);  // 只更新状态为1的用户
int updated = userMapper.update(null, batchUpdate);
// 案例4:乐观锁更新
LambdaUpdateWrapper<Product> optimisticUpdate = new LambdaUpdateWrapper<>();
optimisticUpdate.set(Product::getStock, stock - quantity)
               .set(Product::getVersion, version + 1)
               .eq(Product::getId, productId)
               .eq(Product::getVersion, version)  // 版本号条件
               .ge(Product::getStock, quantity);  // 库存充足条件

性能优化案例

java 复制代码
// 案例:分页查询优化
public Page<User> searchUsersWithOptimization(UserSearchDTO searchDTO, 
                                              int pageNum, 
                                              int pageSize) {

    // 使用游标分页避免深分页性能问题
    Long lastId = searchDTO.getLastId();  // 上一页最后一条记录的ID

    QueryWrapper<User> wrapper = new QueryWrapper<>();

    if (lastId != null) {
        // 使用ID范围查询优化分页
        wrapper.gt("id", lastId)
               .orderByAsc("id")  // 必须按ID升序
               .last("LIMIT " + pageSize);
    } else {
        // 第一页使用传统分页
        wrapper.orderByDesc("create_time")
               .orderByDesc("id");  // 双字段排序避免分页重复数据
    }

    // 添加业务条件
    wrapper.eq("status", 1)
           .eq("deleted", 0);

    // 使用覆盖索引优化
    wrapper.select("id", "username", "email", "avatar", "create_time");

    // 执行查询
    Page<User> page = new Page<>(pageNum, pageSize);
    return userMapper.selectPage(page, wrapper);
}
// 案例2:统计查询优化
public List<Map<String, Object>> getUserStatistics() {
    QueryWrapper<User> wrapper = new QueryWrapper<>();

    // 使用覆盖索引,避免回表
    wrapper.select("dept_id", 
                  "gender", 
                  "COUNT(*) as count",
                  "AVG(age) as avg_age",
                  "SUM(salary) as total_salary")
          .groupBy("dept_id", "gender")
          .having("COUNT(*) > 0")
          .orderByAsc("dept_id", "gender");

    // 使用selectMaps返回统计结果
    return userMapper.selectMaps(wrapper);
}

条件构造器的核心价值

  1. 统一规范查询
  2. 业务逻辑与数据访问解耦
  3. 支持复杂查询场景

性能优势

预编译防注入,提升性能

java 复制代码
// 条件构造器生成预编译SQL
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "张三").eq("age", 25);

// 生成的SQL:SELECT * FROM user WHERE name = ? AND age = ?
// 预编译执行计划可以缓存,提升性能

// 对比字符串拼接:
// SELECT * FROM user WHERE name = '张三' AND age = 25
// 每次都是新的SQL,无法利用预编译缓存

避免N+1查询问题

java 复制代码
// 传统方式可能导致N+1查询
public List<OrderVO> getOrdersWithUser() {
    List<Order> orders = orderMapper.findAll();  // 第一次查询
    for (Order order : orders) {
        User user = userMapper.findById(order.getUserId());  // N次查询
        // ...
    }
}

// 使用条件构造器优化
@Select("SELECT o.*, u.name as user_name, u.phone as user_phone " +
        "FROM order o LEFT JOIN user u ON o.user_id = u.id " +
        "${ew.customSqlSegment}")
List<OrderVO> selectOrdersWithUser(@Param(Constants.WRAPPER) QueryWrapper<Order> wrapper);

// 一次查询搞定所有数据

以上就是博主整理了一天的**【条件构造器**】知识点讲解,对于每一个**【属性方法】**,博主都有写出相对应的代码给大家参考理解,如果在开发时忘记了某个条件的使用,可以看看这篇博客。

相关推荐
CoderYanger2 小时前
动态规划算法-两个数组的dp(含字符串数组):48.最长重复子数组
java·算法·leetcode·动态规划·1024程序员节
西召3 小时前
Spring Kafka 动态消费实现案例
java·后端·kafka
镜花水月linyi3 小时前
ThreadLocal 深度解析(上)
java·后端
镜花水月linyi3 小时前
ThreadLocal 深度解析(下)
java·后端
她说..3 小时前
Spring AOP场景2——数据脱敏(附带源码)
java·开发语言·java-ee·springboot·spring aop
JavaEdge.3 小时前
Spring数据源配置
java·后端·spring
铭毅天下3 小时前
Spring Boot + Easy-ES 3.0 + Easyearch 实战:从 CRUD 到“避坑”指南
java·spring boot·后端·spring·elasticsearch
李慕婉学姐3 小时前
【开题答辩过程】以《基于Springboot的惠美乡村助农系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·spring boot·后端
Cricyta Sevina3 小时前
Java Map 集合深度笔记(理论篇)
java·笔记·哈希算法·map集合