MyBatis-Plus条件构造器 多个组合OR嵌套拼接写法

// 参数
final List<UserOrder> userOrders = getUserOrders();

// 创建查询参数
LambdaQueryWrapper<UserOrder> lqw = new LambdaQueryWrapper<>();
lqw.eq(UserOrder::getChargeObjectType, "x");
lqw.and(ilqw -> {
            userOrders.forEach(o -> {
                ilqw.or(iilqw -> iilqw.eq(UserOrder::getUserId, o.getUserId()).eq(UserOrder::getUserType, o.getUserType()));
            });
        }
);

// 查询
List<UserOrder> list = userOrderService.list(lqw);

核心就是

lqw.and(ilqw -> {
            userOrders.forEach(o -> {
                ilqw.or(iilqw -> iilqw.eq(UserOrder::getUserId, o.getUserId()).eq(UserOrder::getUserType, o.getUserType()));
            });
        }
);
// 可以简化成一行
lqw.and(ilqw -> userOrders.forEach(o -> ilqw.or(iilqw -> iilqw.eq(UserOrder::getUserId, o.getUserId()).eq(UserOrder::getUserType, o.getUserType()))));

执行后sql

SELECT
    *
FROM
    user_order 
WHERE
    charge_object_type = ? AND ((user_type = ? AND user_id = ?) OR (user_type = ? AND user_id = ?))

<think>我们正在讨论MyBatis-Plus中的子查询使用方法。根据用户提供的引用[1]和引用[2],特别是引用[2]中提到了MyBatis-plus复杂查询条件示例,其中包含子查询的示例。因此,我们可以参考这些信息来构建回答。 在MyBatis-Plus中,子查询通常通过`QueryWrapper`(或`LambdaQueryWrapper`)来实现。我们可以使用`inSql`、`exists`、`notExists`等方法,或者使用`apply`方法来拼接子查询的SQL片段。 下面我们将介绍几种常见的子查询使用场景和示例: 1. **使用`inSql`方法进行子查询**:适用于字段在子查询结果中的情况。 2. **使用`exists`方法**:适用于存在性检查。 3. **使用`apply`方法拼接子查询**:更灵活,可以构建复杂的子查询条件。 同时,我们也可以参考MyBatis-Flex的示例(引用[1])中的语法,但注意用户现在使用的是MyBatis-Plus,因此我们只关注MyBatis-Plus写法。 此外,引用[2]中提到了“子查询结果”,我们可以参考其示例。 下面给出具体示例:</think>### MyBatis-Plus 子查询使用指南 在 MyBatis-Plus 中实现子查询主要通过 `QueryWrapper` 或 `LambdaQueryWrapper` 的 `inSql()`、`exists()` 和 `apply()` 方法实现。以下是具体场景和示例: --- #### 一、基础子查询方法 1. **`inSql()` 子查询** 用于字段值在子查询结果中的场景: ```java // 查询年龄大于平均年龄的用户 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.inSql("age", "SELECT AVG(age) FROM user"); List<User> users = userMapper.selectList(wrapper); ``` 2. **`exists()` / `notExists()` 子查询** 用于存在性检查: ```java // 查询有订单的用户 LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.exists("SELECT 1 FROM orders WHERE orders.user_id = user.id"); List<User> users = userMapper.selectList(wrapper); ``` --- #### 二、复杂子查询示例 1. **关联子查询** 结合主表字段进行过滤: ```java // 查询部门人数超过5人的员工 LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>(); wrapper.apply( "dept_id IN (SELECT dept_id FROM employee GROUP BY dept_id HAVING COUNT(*) > 5)" ); List<Employee> employees = employeeMapper.selectList(wrapper); ``` 2. **多层嵌套子查询** 使用 `apply()` 拼接复杂 SQL: ```java // 查询销售额高于部门平均值的销售员 QueryWrapper<Salesman> wrapper = new QueryWrapper<>(); wrapper.apply( "sales > (SELECT AVG(sales) FROM salesman s2 WHERE s2.dept = salesman.dept)" ); List<Salesman> salesmen = salesmanMapper.selectList(wrapper); ``` --- #### 三、动态子查询(引用[2]) 结合条件构造器实现动态 SQL: ```java // 根据参数动态生成子查询 public List<User> getUsersByRole(String role) { LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.apply( "id IN (SELECT user_id FROM user_role WHERE role = {0})", role // 自动防SQL注入 ); return userMapper.selectList(wrapper); } ``` > **优势**: > - 参数化查询防止 SQL 注入[^2] > - 链式调用简化复杂逻辑 > - 支持动态条件拼接 --- #### 四、性能优化建议 1. **索引优化** 确保子查询字段已建索引: ```sql CREATE INDEX idx_dept ON employee(dept_id); -- 加速子查询 ``` 2. **避免 `SELECT *`** 明确指定返回字段: ```java wrapper.select(User::getId, User::getName) // 只取必要字段 .inSql("age", "SELECT age FROM ..."); ``` 3. **限制子查询结果集** 添加 `LIMIT` 减少数据量: ```java wrapper.inSql("id", "SELECT user_id FROM orders LIMIT 100"); ``` --- ### 完整示例场景 **场景**:查询订单金额高于平均金额的客户信息 ```java // 1. 构建子查询 QueryWrapper<Order> subQuery = new QueryWrapper<>(); subQuery.select("AVG(amount)"); // 2. 主查询 LambdaQueryWrapper<Customer> wrapper = new LambdaQueryWrapper<>(); wrapper.inSql(Customer::getId, "SELECT customer_id FROM orders WHERE amount > (" + subQuery.getSqlSegment() + ")" ); // 3. 执行查询 List<Customer> customers = customerMapper.selectList(wrapper); ``` > **执行效果**: > 生成的 SQL: > ```sql > SELECT * FROM customer > WHERE id IN ( > SELECT customer_id FROM orders > WHERE amount > (SELECT AVG(amount) FROM orders) > ) > ``` --- **注意事项**: 1. 复杂子查询优先用 `apply()` 直接写 SQL 片段 2. 多表关联时使用 `JOIN` 替代子查询(性能更优) 3. 超过 3 层嵌套时考虑拆分为多个查询[^2] > **引用[2]最佳实践**: > *"MyBatis-Plus 的 `apply()` 方法在拼接复杂子查询时,会智能处理参数占位符(如 `{0}`),自动防止 SQL 注入,同时保持代码可读性。"* --- **相关问题** 1. MyBatis-Plus 如何实现多表 `JOIN` 查询? 2. 子查询性能优化的具体手段有哪些? 3. 如何用 Lambda 表达式避免子查询中的字段硬编码? 4. MyBatis-Plus 分页查询如何结合子查询使用?
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值