Example 类全场景实战指南

文章目录

  • [MyBatis 逆向工程核心利器:Example 类全场景实战指南](#MyBatis 逆向工程核心利器:Example 类全场景实战指南)
    • [一、什么是 Example 类?](#一、什么是 Example 类?)
    • 二、核心对象关系拆解
    • 三、常见查询场景代码实战
      • [1. 基础单条件与范围查询 (AND)](#1. 基础单条件与范围查询 (AND))
      • [2. 模糊查询 (LIKE) 与 集合查询 (IN)](#2. 模糊查询 (LIKE) 与 集合查询 (IN))
      • [3. 多条件 OR 查询(重点与易错点)](#3. 多条件 OR 查询(重点与易错点))
      • [4. 排序与去重 (ORDER BY & DISTINCT)](#4. 排序与去重 (ORDER BY & DISTINCT))
      • [5. 结合 PageHelper 实现物理分页](#5. 结合 PageHelper 实现物理分页)
    • [四、动态更新:Selective 与 非 Selective 的区别](#四、动态更新:Selective 与 非 Selective 的区别)
    • 五、开发避坑总结

MyBatis 的 Example 类由 MyBatis Generator (MBG) 自动生成,用于在不手写 XML 条件语句的情况下,以纯 Java 面向对象的方式构建动态 SQL(包括单/多条件查询、模糊查询、INOR、分页与排序等)。


MyBatis 逆向工程核心利器:Example 类全场景实战指南

一、什么是 Example 类?

在使用 MyBatis Generator 逆向生成持久层代码时,每个实体类都会对应生成一个 XxxExample 类。

它的核心思想是 通过面向对象 API 组装 SQL 的 WHERE 子句 。底层通过维护一个 Criteria 列表,自动拼接 SQL 中的 ANDORLIKEIN 等条件,避免了手动在 XML 中编写大量繁琐的 <if test="..."> 标签。


二、核心对象关系拆解

在开始编码前,先理清 Example 内部的三个关键角色:

  • XxxExample :查询的主体入口。负责管理排序(orderByClause)、去重(distinct)以及多个 Criteria 之间的逻辑连接。
  • Criteria :条件容器。单个 Criteria 内的所有条件默认用 AND 拼接。
  • **createCriteria() vs or()**
  • example.createCriteria():创建主条件容器(默认第一个 Criteria)。
  • example.or():新建一个 Criteria 并将其与之前的条件用 OR 连接。

三、常见查询场景代码实战

假设逆向生成的表为用户表 user,对应实体为 User,Mapper 为 UserMapper,条件构造类为 UserExample

1. 基础单条件与范围查询 (AND)

目标 SQL:

sql 复制代码
SELECT * FROM user 
WHERE status = 1 
  AND age >= 18 
  AND age <= 30;

Java 代码实现:

java 复制代码
UserExample example = new UserExample();
UserExample.Criteria criteria = example.createCriteria();

// 链式调用拼接 AND 条件
criteria.andStatusEqualTo(1)
        .andAgeGreaterThanOrEqualTo(18)
        .andAgeLessThanOrEqualTo(30);

List<User> users = userMapper.selectByExample(example);

2. 模糊查询 (LIKE) 与 集合查询 (IN)

目标 SQL:

sql 复制代码
SELECT * FROM user 
WHERE username LIKE '%jack%' 
  AND role_id IN (1, 2, 3);

Java 代码实现:

java 复制代码
UserExample example = new UserExample();
UserExample.Criteria criteria = example.createCriteria();

// LIKE 模糊查询需自行拼接通配符 %
criteria.andUsernameLike("%jack%")
        .andRoleIdIn(Arrays.asList(1, 2, 3));

List<User> users = userMapper.selectByExample(example);

3. 多条件 OR 查询(重点与易错点)

目标 SQL:

sql 复制代码
SELECT * FROM user 
WHERE (dept_id = 10 AND status = 1) 
   OR (dept_id = 20 AND role_id = 2);

Java 代码实现:

java 复制代码
UserExample example = new UserExample();

// 第一个 Criteria (dept_id = 10 AND status = 1)
UserExample.Criteria criteria1 = example.createCriteria();
criteria1.andDeptIdEqualTo(10)
         .andStatusEqualTo(1);

// 调用 or() 生成第二个 Criteria,二者以 OR 连接
UserExample.Criteria criteria2 = example.or();
criteria2.andDeptIdEqualTo(20)
         .andRoleIdEqualTo(2);

List<User> users = userMapper.selectByExample(example);

4. 排序与去重 (ORDER BY & DISTINCT)

目标 SQL:

sql 复制代码
SELECT DISTINCT * FROM user 
WHERE status = 1 
ORDER BY create_time DESC, id ASC;

Java 代码实现:

java 复制代码
UserExample example = new UserExample();
example.createCriteria().andStatusEqualTo(1);

// 开启去重
example.setDistinct(true);

// 传入原生 SQL 排序片段(注意 SQL 注入风险,字段名需硬编码或校验)
example.setOrderByClause("create_time DESC, id ASC");

List<User> users = userMapper.selectByExample(example);

5. 结合 PageHelper 实现物理分页

Example 类本身不包含特定数据库的分页语法(如 MySQL 的 LIMIT)。生产环境中通常搭配 PageHelper 使用:

java 复制代码
// 开启分页(第 1 页,每页 10 条)
PageHelper.startPage(1, 10);

UserExample example = new UserExample();
example.createCriteria().andStatusEqualTo(1);
example.setOrderByClause("id DESC");

// 紧随其后的 select 语句会被自动拦截并加上 LIMIT
List<User> list = userMapper.selectByExample(example);
PageInfo<User> pageInfo = new PageInfo<>(list);

四、动态更新:Selective 与 非 Selective 的区别

Example 还可配合 updateByExample 族函数完成批量/条件更新:

java 复制代码
User updateUser = new User();
updateUser.setStatus(0); // 仅更新状态为停用

UserExample example = new UserExample();
example.createCriteria().andLastLoginTimeLessThan(oneYearAgoDate);

// 场景 A:推荐 - 只更新 entity 中非 NULL 的字段
userMapper.updateByExampleSelective(updateUser, example);
// 对应 SQL: UPDATE user SET status = 0 WHERE last_login_time < ?

// 场景 B:谨慎使用 - 会将 entity 中为 NULL 的属性一并覆盖到数据库
userMapper.updateByExample(updateUser, example);
// 对应 SQL: UPDATE user SET username = NULL, status = 0, ... WHERE last_login_time < ?

五、开发避坑总结

关注点 说明与排查建议
禁止复用对象 每次业务查询**必须 new 一个新的 Example**。旧对象内保留了历史 criteria 列表,复用会导致 SQL 条件无限追加。
or() 陷阱 example.or() 创建的是一个全新的 Criteria 分支。不要误以为在同一个 Criteria 实例内有 .orEqualTo() 这种方法。
NULL 值安全 andXxxEqualTo(val) 若传入 null 会直接抛出异常;若需匹配 IS NULL,必须调用专用的 andXxxIsNull() 方法。
复杂多表关联 Example 只适合单表的 CRUD;涉及多表 JOIN、复杂子查询或聚合函数计算时,应回归 XML 手写 SQL 以保障可控性与执行性能。

相关推荐
两点王爷1 小时前
SpringBoot 项目集成 GeoServer 源码,实现地图服务发布
java·spring boot·后端
Javatutouhouduan2 小时前
Java如何速通性能优化难题?
java·java面试·jvm调优·后端开发·java程序员·java八股文·java性能优化
lemon_sjdk2 小时前
DOM 节点
java·前端·javascript
leoZ2312 小时前
2026-09-09-springboot-cloud-deploy-pitfalls
java·前端·javascript·vue.js·人工智能·spring boot·后端
驭渊的小故事3 小时前
多线程02
java·开发语言·jvm
随遇而安zx3 小时前
【多线程】---实战:CompletableFuture编排
java·多线程·并发
Wang's Blog3 小时前
Java框架快速入门: Spring Security+OAuth2之HTTP请求结构与认证基础
java·spring·http
君顾13 小时前
本地折扣卡 CPS 平台搭建:从系统架构到落地实战
java·开发语言·折扣卡
Java小白笔记4 小时前
Java 单元测试怎么写:JUnit 5、Mockito 与 Spring Boot 方法级实战
java·junit·单元测试