Example API指南2

文章目录

  • [揭秘极简风格: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(而不是 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 (),会导致数据库直接报语法错误。
相关推荐
CallFay云起未来12 小时前
AI客服上线后多久才能回本?从TCO到ROI的完整测算方法
java·大数据·人工智能·架构·文心一言
Sam_Deep_Thinking12 小时前
什么是CountDownLatch?
java·后端·面试·程序员
小蒜学长12 小时前
基于SpringBoot和Vue的低卡食品销售系统的设计与实现(代码+数据库+LW)
java·后端·springboot·健康管理·低卡食品销售系统
CRMEB系统商城12 小时前
前后端技术栈全面换代!CRMEB 多商户(Java)v3.0更新预告
java·开发语言·小程序·php
Sayai12 小时前
Neo4j 内嵌模式(Embedded)实战:Java 嵌入式 vs 服务端部署的写入性能对比与 GC 调优
java·开发语言·性能优化·neo4j·图数据库
木头科技12 小时前
AI 工程化第四篇】Spring AI Agent 线上可观测实战:Token 成本、调用链、工具耗时、RAG 命中率怎么监控
java·人工智能·spring
m0_7341724213 小时前
Python列表切片为什么不改变原列表
java
kiss strong13 小时前
idea显示前进后退按钮
java·ide·intellij-idea
caoerzhong13 小时前
跨境海外仓怎么管:JeeWMS 开源 Java 仓库管理系统打通头程、海外仓与尾程
java·开发语言·开源
MayBaymax13 小时前
Elasticsearch 原理与用法
java·elasticsearch