logo 范 · 拾光录
网址收集 关于作者 Github Gitee
杂文随笔4
Hexo博客:基础使用Hexo博客:Next主题Hexo博客:Next进阶使用Hexo博客:Next高级配置
前端编程3
前端基础知识16
UniApp15
Vue框架19
Java编程7
Java基础知识14
SpringBoot31
SpringMVC14
MyBatis8
SpringCloud15
RocketMQ1
MyCat1
数据库4
MySQL6
Redis7
MongoDB10
H21
Java技术栈4
知识整理分布式锁的实现方案MySQL事务MySQL的锁
软件工具箱14
IDEAGitMavenGradleNginx安装Nginx配置JMeter压测OllamaPicGoRustFSVSCodeDockerObsidianObs录制
Linux知识11
树莓派安装及使用ArchLinux:常用软件ArchLinux:基础系统安装ArchLinux:深度优化ArchLInux:图形化界面安装ArchLinux:Nirifrp内网穿透Jar启动脚本Linux常用命令VirtualBox安装CentOSVirtualBox安装Ubuntu
Python编程6
Python基础知识Python语法yolo目标检测OpenCV的使用及树莓派平台condauv
创意设计2
Blender:入门知识UI设计基础知识
AI相关9
Claude CodeHermes AgentOpenAI基本使用OpenAI工具调用OpenAI记忆管理OpenAI推理执行OpenAI开发框架Langchainllama.cpp

核心问题

SQL 中 AND 优先级高于 OR。MyBatis-Plus 的 Wrapper 链式调用如果不显式分组,生成的 SQL 括号位置可能与预期不符,导致筛选条件失效。

场景一:OR 与后续 AND 条件混用

错误写法

// 意图:查 (我的房源 或 团队房源) 且满足后续筛选条件
wrapper.in(TbHouse::getUserId, ids)
       .or()
       .eq(TbHouse::getTeamId, params.getTeamId());
// 后续追加
wrapper.eq(TbHouse::getRentSale, params.getRentSale());
wrapper.eq(TbHouse::getStatus, params.getStatus());

生成的 SQL(错误)

WHERE user_id IN (?,?,?)
   OR team_id = ? AND rent_sale = ? AND status = ?

由于 AND > OR,实际逻辑等价于:

WHERE user_id IN (?,?,?)
   OR (team_id = ? AND rent_sale = ? AND status = ?)

后果: user_id IN 分支完全绕过了 rent_salestatus 筛选,导致查询结果包含不该出现的数据。

正确写法

wrapper.and(w -> w.in(TbHouse::getUserId, ids)
                  .or()
                  .eq(TbHouse::getTeamId, params.getTeamId()));
// 后续条件正常追加
wrapper.eq(TbHouse::getRentSale, params.getRentSale());
wrapper.eq(TbHouse::getStatus, params.getStatus());

生成的 SQL(正确)

WHERE (user_id IN (?,?,?) OR team_id = ?)
  AND rent_sale = ?
  AND status = ?

记忆口诀

只要链式调用了 .or(),且后续还需要追加 AND 条件,就必须用 .and() 包裹 OR 组。

场景二:多字段模糊搜索(有意的 OR 组)

这种场景 .and() 本身就是正确的用法:

// 多个字段模糊匹配,任一命中即可
wrapper.and(w -> w.like(TbHouse::getName, keyword)
                  .or()
                  .like(TbHouse::getDoorplate, keyword)
                  .or()
                  .like(TbHouse::getOwnerName, keyword));
// 这里 and() 内的 OR 不受外部 AND 条件影响,正确
wrapper.eq(TbHouse::getStatus, 1); // 额外筛选

生成:

WHERE (name LIKE '%kw%' OR doorplate LIKE '%kw%' OR owner_name LIKE '%kw%')
  AND status = 1

.and()的本质

.and(Consumer<Wrapper> consumer) 创建一个用括号包裹的子条件组,以 AND 方式连接到外层:

写法 SQL
wrapper.eq(A, 1).eq(B, 2) WHERE a=1 AND b=2
wrapper.eq(A, 1).or().eq(B, 2) WHERE a=1 OR b=2
wrapper.and(w -> w.eq(A, 1).or().eq(B, 2)) WHERE (a=1 OR b=2)
wrapper.and(w -> w.eq(A, 1).or().eq(B, 2)).eq(C, 3) WHERE (a=1 OR b=2) AND c=3

注意区分 and()and(Consumer)

排查方法

当遇到"加了筛选条件但结果不对"时:

  1. 开启 MyBatis-Plus SQL 日志:mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
  2. 观察实际执行的 SQL 括号位置
  3. 检查代码中 .or() 是否被 .and() 正确包裹
核心问题
场景一:OR 与后续 AND 条件混用
错误写法
正确写法
记忆口诀
场景二:多字段模糊搜索(有意的 OR 组)
.and()的本质
排查方法