MyBatis-Plus 中 nested() 与 and() 方法详解(最佳实践场景)

2025-07-03 17:50

本文主要是介绍MyBatis-Plus 中 nested() 与 and() 方法详解(最佳实践场景),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《MyBatis-Plus中nested()与and()方法详解(最佳实践场景)》在MyBatis-Plus的条件构造器中,nested()和and()都是用于构建复杂查询条件的关键方法,但...

MyBatis-Plus 中nested()与and()方法详解

在 MyBatis-Plus 的条件构造器中,nested()and() 都是用于构建复杂查询条件的关键方法,但它们在功能和使用场景上有显著差异。

一、核心区别对比

特性and()nested()
主要用途连接多个条件(默认AND)创建嵌套查询条件
括号生成❌ 不生成括号✅ 自动生成括号包裹内部条件
逻辑关系与外部条件默认AND连接可作为独立逻辑单元
复杂查询支持有限,适合简单条件组合强大,支持任意层级嵌套
OR 条件处理需要显式使用or()天然支持OR条件嵌套
SQL 表现平铺条件生成带括号的子表达式

二、方法详解

1.and()方法

  • 功能:连接多个查询条件,默认使用 AND 逻辑
  • 特点
    • 不会生成括号
    • 适用于简单的条件组合
    • 当需要 OR 逻辑时需显式调用 or()
使用示例:
// 查询年龄大于18且姓张的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18)
       .and(wq -> wq.like("name", "张"));

生成 SQL

WHERE age > 18 AND name LIKE '%张%'

2.nested()方法

  • 功能:创建嵌套查询条件(自动添加括号)
  • 特点
    • 自动生成括号包裹内部条件
    • 支持任意层级的复杂嵌套
    • 特别适合处理 OR 逻辑组合
    • 使SQL逻辑更清晰
使用示例:
// 查询(年龄>30 或 工资>10000) 且 状态为激活的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.nested(nq -> 
        nq.gt("age", 30).or().gt("salary", 10000))
    .eq("status", 1);

生成 SQL

WHERE (age > 30 OR salary > 10000) AND status = 1

三、高级用法对比

1. 复杂 OR 条件处理

使用 and() 实现:

wrapper.and(wq -> wq.gt("age", 30).or().gt("salary", 10China编程000))
       .eq("status", 1);
-- 逻辑错误!实际生成:
WHERE (age > 30 OR salary > 10000 AND status = 1)
-- 正确应使用括号包裹OR条件

使用 nested() 实现:

wrapper.nested(nq -> nq.gt("age", 30).or().gt("salary", 10000))
       .eq("status", 1);
-- 正确生成:
WHERE (age > 30 OR salary > 10000) AND status = 1

2. 多层级嵌套

nested() 支持无限嵌套:

wrapper.nested(nq1 -> 
    nq1.eq("type", 1)
       .nested(nq2 -> 
           nq2.lt("age", 20).or().gt("age", 60))
    )
    .like("name", "张");

生成 SQL

WHERE (type = 1 AND (age < 20 OR age > 60)) 
AND name LIKE '%张%'

四、最佳实践场景

使用and()当:

  1. 构建简单的 AND 条件组合
  2. 不需要改变条件优先级
  3. 查询条件逻辑简单平铺

使用nested()当:

  1. 需要处理 OR 条件组合
  2. 需要改变条件运算优先级
  3. 构建复杂嵌套查询
  4. 需要清晰分隔逻辑单元
  5. 处理多条件分支逻辑

混合使用示例:

wrapper.eq("dept_id", 10)
       .nested(nq -> 
           nq.like("name", "张")
             .or()
             .nested(nq2 -> 
                 nq2.gt("salary", 10000).lt("age", 40))
       );

生成 SQL

WHERE dept_id = 10 
AND (name LIKE '%张%' OR (salary > 10000 AND age < 40))

五、原理分析

1.and()实现原理

public Children and(Consumer<Param> consumer) {
    return addNestedCondition(true, consumer);
}
  • 内部调用 addNestedCondition
  • 参数 true 表示使用 AND 连接
  • 不添加括号

2.nested()实现原理

public Children nested(Consumer<Param> consumer) {
    return addNestedCondition(false, consumer);
}
  • 参数 faChina编程lse 表示不指定连接类型
  • 自动添加括号包裹表达式
  • 可作为独立逻辑单元嵌入

六、常见误区

  1. 错误认为 and() 会加括号

    • ✅ 只有 nested() 会生成括号
  2. 在 OR 条件中错误使用 and()

    // 错误:OR条件未正确包裹
    wrapper.eq("a", 1)
           .or()
           .and(wq -> wq.eq("b", 2).eq("c", 3));
    // 正确:使用nested
    wrapper.eq("a", 1)
           .or()
           .nested(nq -> nq.eq("b", 2).eq("c", 3));
  3. 忽略条件优先级

    // 错误:AND/OR优先级问题
    wrapper.eq("status", 1)
           .or()
           .eq("deleted", 0)
           .eq("name", "test");
    // 正确:使用nested明确优先级
    wrapper.nested(nq -> nq.eq("status", 1).or().eq("deleted", 0))
           .eq("name", "test");

七、性能考虑

  1. 数据库优化

    • 嵌套条件可能影响查询优化器的工作
    • 避免超过3层嵌套(影响可读性和性能)
  2. 索引利用

    // 好的实践:索引列前置
    wrapper.nested(nq -> 
        nq.eq("indexed_column1", val1)  // 索引列
           .or()
           .eq("indexed_column2", val2) // 索引列
    );
    // 避免:非索引列前置
    wrapper.nested(nq -> 
        nq.eq("non_indexed", val)      // 非索引列
           .or()
           .eq("indexed_column", val)   // 索引列
    );

总结

场景推荐方法
简单AND条件组合and()
OR条件组合nested()
改变条件优先级nested()
多层级复杂查询nested()
逻辑单元清晰分隔nested()lgCKoXa

经验法则

当需要括号来明确查询逻辑时,总是使用 nested()
当只是简单添加lgCKoXaAND条件时,使用 and()

正确使用这两个方法可以使你的MyBatis-Plus查询:

  1. 逻辑更清晰
  2. 优先级更明确
  3. 更易维护
  4. 充分利用数据库优化能力
  5. 避免难以调试的逻辑错误

到此这篇关于MyBatis-Plus 中 nested() 与 and() 方法详解的文章就介绍到这了,更多相关MyBatis-Plus nested() 与 and() 内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.cppcnphps.com)!

这篇关于MyBatis-Plus 中 nested() 与 and() 方法详解(最佳实践场景)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155285

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

MyBatis常用XML语法详解

《MyBatis常用XML语法详解》文章介绍了MyBatis常用XML语法,包括结果映射、查询语句、插入语句、更新语句、删除语句、动态SQL标签以及ehcache.xml文件的使用,感兴趣的朋友跟随小... 目录1、定义结果映射2、查询语句3、插入语句4、更新语句5、删除语句6、动态 SQL 标签7、ehc

JDK21对虚拟线程的几种用法实践指南

《JDK21对虚拟线程的几种用法实践指南》虚拟线程是Java中的一种轻量级线程,由JVM管理,特别适合于I/O密集型任务,:本文主要介绍JDK21对虚拟线程的几种用法,文中通过代码介绍的非常详细,... 目录一、参考官方文档二、什么是虚拟线程三、几种用法1、Thread.ofVirtual().start(

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D