文章目录
- [揭秘极简风格:TkMyBatis 通用 Example 类实战指南](#揭秘极简风格:TkMyBatis 通用 Example 类实战指南)
-
- [一、为什么你用的是统一的 `Example`?](#一、为什么你用的是统一的
Example?) - 二、基础语法与初始化机制
- 三、高频实战场景代码
-
- [1. 基础 AND 条件查询](#1. 基础 AND 条件查询)
- [2. 模糊查询 (LIKE) 与 集合过滤 (IN)](#2. 模糊查询 (LIKE) 与 集合过滤 (IN))
- [3. 多分支 OR 查询](#3. 多分支 OR 查询)
- [4. 排序 (ORDER BY) 与指定查询列 (SelectProperties)](#4. 排序 (ORDER BY) 与指定查询列 (SelectProperties))
- [5. 结合 PageHelper 分页查询](#5. 结合 PageHelper 分页查询)
- 四、动态条件拼接最佳实践
- [五、TkMyBatis 的 `Example.builder` 链式进阶语法](#五、TkMyBatis 的
Example.builder链式进阶语法) - 六、关键避坑点
- [一、为什么你用的是统一的 `Example`?](#一、为什么你用的是统一的
你代码里直接使用 Example(而不是 UserExample、OrderExample 等表名专属类),说明你的项目使用的并不是 MyBatis 官方原生的 MyBatis Generator (MBG),而是国内非常主流的 TkMyBatis (通用 Mapper,作者 Abel533)。
在 TkMyBatis 中,官方提供了一个统配所有实体类的通用泛型容器:tk.mybatis.mapper.entity.Example。
揭秘极简风格:TkMyBatis 通用 Example 类实战指南
一、为什么你用的是统一的 Example?
| 对比项 | 官方原生 MyBatis Generator | TkMyBatis 通用 Mapper |
|---|---|---|
| 类的全类名 | 自动生成在各实体包下的 com.xxx.model.UserExample |
统一引用 tk.mybatis.mapper.entity.Example |
| 文件生成量 | 每张表都需要生成一个数千行的 Java 文件 | 零物理生成,由框架提供统一的通用类 |
| 实现原理 | 编译期强类型绑定方法(如 andAgeEqualTo) |
运行时反射 解析实体类属性或 @Column 注解 |
TkMyBatis 的核心设计思想是通过实体类型 Class<T> 初始化上下文,从而省去了庞大的代码生成负担。
二、基础语法与初始化机制
创建 Example 时,必须将实体类的 Class 传入构造函数:
java
import tk.mybatis.mapper.entity.Example;
// 1. 初始化,指定作用的实体类
Example example = new Example(User.class);
// 2. 创建条件容器
Example.Criteria criteria = example.createCriteria();
特别注意(新手最易踩坑点):
传给条件方法的字段名,默认是Java 实体类的属性名(驼峰命名,如
userId、userName) ,而不是数据库底层的下划线字段名(user_id、user_name),TkMyBatis 会自动完成映射转换。
三、高频实战场景代码
1. 基础 AND 条件查询
目标 SQL:
sql
SELECT * FROM user
WHERE status = 1
AND age >= 18
AND age <= 30;
Java 代码:
java
Example example = new Example(User.class);
example.createCriteria()
.andEqualTo("status", 1)
.andGreaterThanOrEqualTo("age", 18)
.andLessThanOrEqualTo("age", 30);
List<User> users = userMapper.selectByExample(example);
2. 模糊查询 (LIKE) 与 集合过滤 (IN)
目标 SQL:
sql
SELECT * FROM user
WHERE user_name LIKE '%jack%'
AND role_id IN (1, 2, 3);
Java 代码:
java
Example example = new Example(User.class);
example.createCriteria()
.andLike("userName", "%jack%") // 属性名 userName,需手写 %
.andIn("roleId", 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
Example example = new Example(User.class);
// 第一个括号的分支 (deptId = 10 AND status = 1)
Example.Criteria criteria1 = example.createCriteria();
criteria1.andEqualTo("deptId", 10)
.andEqualTo("status", 1);
// 新建第二个 Criteria 并用 OR 连接
Example.Criteria criteria2 = example.or();
criteria2.andEqualTo("deptId", 20)
.andEqualTo("roleId", 2);
List<User> users = userMapper.selectByExample(example);
4. 排序 (ORDER BY) 与指定查询列 (SelectProperties)
TkMyBatis 在通用 Example 上扩展了非常便利的专属 API:
java
Example example = new Example(User.class);
example.createCriteria().andEqualTo("status", 1);
// 方式一:面向属性名的安全排序(推荐,防止 SQL 注入)
example.orderBy("createTime").desc().orderBy("id").asc();
// 方式二:直接书写 SQL 排序片段
// example.setOrderByClause("create_time DESC, id ASC");
// 仅查询指定列(相当于 SELECT id, user_name),避免 SELECT *
example.selectProperties("id", "userName");
List<User> users = userMapper.selectByExample(example);
5. 结合 PageHelper 分页查询
在基于 TkMyBatis 的工程中,分页通常与 PageHelper 原生搭配:
java
PageHelper.startPage(1, 10);
Example example = new Example(User.class);
example.createCriteria().andEqualTo("status", 1);
example.orderBy("createTime").desc();
List<User> list = userMapper.selectByExample(example);
PageInfo<User> pageInfo = new PageInfo<>(list);
四、动态条件拼接最佳实践
面对前端传入的动态搜索筛选(字段可能为空),常规写法是叠加 if 分支:
java
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
if (dto.getStatus() != null) {
criteria.andEqualTo("status", dto.getStatus());
}
if (StringUtils.hasText(dto.getUserName())) {
criteria.andLike("userName", "%" + dto.getUserName() + "%");
}
if (dto.getRoleIds() != null && !dto.getRoleIds().isEmpty()) {
criteria.andIn("roleId", dto.getRoleIds());
}
List<User> list = userMapper.selectByExample(example);
五、TkMyBatis 的 Example.builder 链式进阶语法
TkMyBatis 还提供了更现代的 Builder 风格,可以将上述逻辑进一步压缩:
java
Example example = Example.builder(User.class)
.select("id", "userName", "status")
.where(WeekendSqls.<User>custom()
.andEqualTo(User::getStatus, 1)
.andLike(User::getUserName, "%jack%"))
.orderByDesc("createTime")
.build();
List<User> users = userMapper.selectByExample(example);
提示 :如果使用的是
WeekendSqls,支持通过 Java 8 方法引用(如User::getUserName)来避免写错字符串属性名。
六、关键避坑点
- 传参是属性名,不是列名 :调用
andEqualTo("userId", 1),写userId(Java 属性),不要 写user_id(数据库列名),否则会抛出找不到属性的反射异常。 - **每次查询必须全新
new Example()**:不可跨请求复用Example单例,否则多线程并发时条件会混乱,且历史查询条件会被持续追加。 - 空集合保护 :使用
andIn("roleId", list)时,务必先判断list != null && !list.isEmpty()。如果传入空集合,拼接出的 SQL 为WHERE role_id IN (),会导致数据库直接报语法错误。