Example API指南2
·
文章目录
你代码里直接使用 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 传入构造函数:
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:
SELECT * FROM user
WHERE status = 1
AND age >= 18
AND age <= 30;
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:
SELECT * FROM user
WHERE user_name LIKE '%jack%'
AND role_id IN (1, 2, 3);
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:
SELECT * FROM user
WHERE (dept_id = 10 AND status = 1)
OR (dept_id = 20 AND role_id = 2);
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:
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 原生搭配:
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 分支:
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 风格,可以将上述逻辑进一步压缩:
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 (),会导致数据库直接报语法错误。
更多推荐




所有评论(0)