- 后端
- ORM
- 数据库
【免费下载链接】Mapper
Mybatis Common Mapper - Easy to use
本指南围绕 tk.mybatis 通用 Mapper 6.0.0(仓库根目录 README.md)展开,系统讲解其版本选型、依赖引入、通用方法体系、Spring Boot 集成与全局配置,并结合仓库源码(core、base、extra 等模块)揭示其 SQL 自动生成的底层原理。读完本文,你将能够在 JDK 17 与 Spring Boot 4 项目中快速引入通用 Mapper,用极少的代码完成单表增删改查,并能按需设计属于自己的通用方法。
为什么需要通用 Mapper
传统 MyBatis 开发中,每张表都要手写实体类、Mapper 接口与 XML(或注解)SQL,selectByPrimaryKey、insert、updateByPrimaryKey、deleteByPrimaryKey这类样板代码重复度极高。通用 Mapper 解决的正是在此问题:它把单表 CRUD 中"套路化"的方法预先定义在通用接口中,由框架根据实体类上的 JPA 注解(@Table、@Id、@Column等)在运行时自动生成对应 SQL。
需要注意的是,仓库 README 明确说明了其能力边界:
- 极其方便地使用 MyBatis 单表的增删改查;
- 支持单表操作,不支持通用的多表联合查询。
多表查询仍应使用手写 SQL(XML 或注解)方式完成。同时,通用 Mapper 允许你"随意的按照自己的需要选择通用方法",也"可以很方便的开发自己的通用方法",这是其可扩展性设计的核心。
版本与分支选择
通用 Mapper 6 与不同 Spring Boot 大版本严格对应,请根据项目实际情况选择对应分支。以下是仓库 README.md 中给出的版本匹配表:
| 分支 | Spring Boot 版本 | JDK 版本 | Mapper 版本 |
|---|---|---|---|
| master | Spring Boot 4.x | JDK 17+ | 6.0.0+ |
| 5.x | Spring Boot 3.x | JDK 17+ | 5.0.0 |
| 4.3.x | Spring Boot 2.x | JDK 8+ | 4.3.x |
从仓库根 pom.xml 可以看到 6.0.0 版本的关键依赖与编译约束:
maven.compiler.source/target均为 17;jakarta.persistence-api版本为 3.2.0(Jakarta JPA 注解);mybatis版本为 3.5.19;- 聚合模块
mapper-modules下包含all、base、core、extra、spring、weekend、generator、spring-boot-starter、solon-plugin等子模块。
引入 Maven 依赖
在 Spring Boot 4.x / JDK 17 项目中使用 6.0.0,直接在pom.xml中引入:
<dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>6.0.0</version> </dependency>该坐标对应 all/mapper 聚合产物,内部整合了核心(core)、基础方法(base)、扩展方法(extra)与 Spring 集成(spring)等能力。若只需基础能力,也可按需引入mapper-core、mapper-base、mapper-extra等独立坐标(见 all/pom.xml 中的dependencyManagement声明)。
若使用 Spring Boot 2.x / JDK 8,请选择 4.3.x 分支;Spring Boot 3.x / JDK 17 请选择 5.x 分支。
6.0 的核心变化:JDK 17 + Jakarta JPA 注解 + Spring Boot 4
6.0 版本的技术栈底座发生了根本性变化,README.md 对此说明如下:
- 基于JDK 17 + Jakarta JPA 注解 + Spring Boot 4;
- 配置完全兼容,但实体类需要改用新版本的 JPA 注解(
jakarta.persistence.*,如jakarta.persistence.Id、jakarta.persistence.Table); - 同步更新(copy)了
mybatis-spring 4.0.0与mybatis-spring-boot-starter 4.0.0; - 此次更新主要是依赖的更新,目标是适配最新的 Spring Boot 4.0.2,提供更好的兼容性和稳定性。
这一变化在仓库测试代码中有直接印证。例如 base 测试实体 Country 中主键注解已使用:
import jakarta.persistence.Id; public class Country implements Serializable { @Id private Long id; private String countryname; private String countrycode; ... }如果你从旧版(javax.persistence.*)迁移,需要同步替换实体类中的 JPA 注解包名,业务配置代码则无需改动。
快速上手:第一个通用 Mapper
参考 base 模块测试,一个最小可用的通用 Mapper 只需三步。
第一步:定义实体类
使用 JPA 注解标注主键与表映射(表名、列名默认由实体类名/属性名按驼峰转下划线规则推导):
import jakarta.persistence.Id; public class Country implements Serializable { @Id private Long id; private String countryname; private String countrycode; // getter / setter 省略 }第二步:继承通用 Mapper 接口
import tk.mybatis.mapper.common.Mapper; public interface CountryMapper extends Mapper<Country> { }CountryMapper本身是空接口,但继承了 Mapper 后即获得一整套通用方法。查看源码可见其继承结构:
@RegisterMapper public interface Mapper<T> extends BaseMapper<T>, ExampleMapper<T>, RowBoundsMapper<T>, SaveMapper<T>, Marker { }而 BaseMapper 再聚合了查询、插入、更新、删除四组基础接口:
@RegisterMapper public interface BaseMapper<T> extends BaseSelectMapper<T>, BaseInsertMapper<T>, BaseUpdateMapper<T>, BaseDeleteMapper<T> { }第三步:注册扫描并在业务中使用
在 MyBatis 配置中注册该 Mapper(base 测试 mybatis-config.xml 的注册方式):
<mappers> <mapper class="tk.mybatis.mapper.base.CountryMapper"/> </mappers>同时使用 MapperHelper 处理 Configuration,通用 Mapper 会将ProviderSqlSource替换为真实 SQL(测试基类 BaseTest 中mapperHelper.processConfiguration(...)即演示了非 Spring 环境下的接入方式)。
接入完成后即可直接调用通用方法:
CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); Country country = mapper.selectByPrimaryKey(1L); // 按主键查询 mapper.insert(country); // 插入 mapper.updateByPrimaryKey(country); // 按主键更新 mapper.deleteByPrimaryKey(1L); // 按主键删除通用方法全景
仓库 base 与 core 模块将通用方法按功能拆分为细粒度接口,便于"按需选择"。从源码结构看,主要分组如下:
| 分组 | 接口 | 代表方法 |
|---|---|---|
| 基础查询 | SelectMapper、SelectByPrimaryKeyMapper、SelectAllMapper、SelectOneMapper、SelectCountMapper、ExistsWithPrimaryKeyMapper | select、selectByPrimaryKey、selectAll、selectOne、selectCount、existsWithPrimaryKey |
| 基础插入 | InsertMapper、InsertSelectiveMapper | insert、insertSelective |
| 基础更新 | UpdateByPrimaryKeyMapper、UpdateByPrimaryKeySelectiveMapper | updateByPrimaryKey、updateByPrimaryKeySelective |
| 基础删除 | DeleteByPrimaryKeyMapper、DeleteMapper | deleteByPrimaryKey、delete |
| 条件查询 | SelectByConditionMapper、SelectCountByConditionMapper、DeleteByConditionMapper、UpdateByConditionMapper、UpdateByConditionSelectiveMapper | selectByCondition、selectCountByCondition等 |
| Example | SelectByExampleMapper、SelectCountByExampleMapper、SelectOneByExampleMapper、DeleteByExampleMapper、UpdateByExampleMapper、UpdateByExampleSelectiveMapper | selectByExample、deleteByExample等 |
| Ids 批量 | SelectByIdsMapper、DeleteByIdsMapper | selectByIds、deleteByIds |
| RowBounds 分页 | SelectRowBoundsMapper、SelectByExampleRowBoundsMapper、SelectByConditionRowBoundsMapper | selectByRowBounds等 |
| 特殊 | InsertListMapper、InsertUseGeneratedKeysMapper | 批量插入、useGeneratedKeys插入 |
| SQL Server 方言 | SqlServerMapper下InsertMapper、InsertSelectiveMapper | SQL Server 方言插入 |
以 SelectByExampleMapper 为例,每个方法通过 MyBatis 的@SelectProvider注解绑定到 Provider 类:
@SelectProvider(type = ExampleProvider.class, method = "dynamicSQL") List<T> selectByExample(Object example);dynamicSQL是 MapperTemplate 定义的占位方法,真正的 SQL 由框架在启动阶段生成并替换。
组合接口:按需拼装
仓库提供了多种预置组合接口,避免逐一继承细粒度接口:
BaseMapper<T>:基础增删改查;Mapper<T>:BaseMapper + ExampleMapper + RowBoundsMapper + SaveMapper;MySqlMapper<T>:追加 MySQL 相关方法(如批量插入);SqlServerMapper<T>、ConditionMapper<T>、ExampleMapper<T>、IdsMapper<T>、SaveMapper<T>等。
这些接口统一标注了@RegisterMapper(见 RegisterMapper.java),会被 MapperHelper 自动识别注册。
深入原理:SQL 是如何自动生成的
通用 Mapper 的核心类是 MapperHelper,其注释直接标明"处理主要逻辑,最关键的一个类"。关键链路如下:
- 注册通用接口:
registerMapper(Class<?>)遍历接口中声明的方法,读取方法上的@SelectProvider/@InsertProvider/@DeleteProvider/@UpdateProvider注解,找到对应的 Provider 模板类,并通过反射实例化 MapperTemplate 子类(如BaseSelectProvider、ExampleProvider)。若注解缺失或模板类非法,则回退到EmptyProvider。 - 方法注册:
addMethodMap(methodName, method)将每个通用方法名绑定到模板类中同名方法,供后续 SQL 生成调用。 - 自动注册继承接口:
registerMapper会递归注册当前接口的所有父接口,因此CountryMapper extends Mapper<T>时,Mapper、BaseMapper以及更细粒度的接口会被依次注册。 - 处理 MappedStatement:
processConfiguration(Configuration)遍历 MyBatisConfiguration中全部MappedStatement,对命中的通用方法调用setSqlSource,将占位ProviderSqlSource替换为基于 XML 动态 SQL(XMLLanguageDriver)构建的真实SqlSource——参见 MapperTemplate.createSqlSource。 - 实体解析:SQL 生成依赖 EntityHelper 与 DefaultEntityResolve 解析实体类注解,得到表名、列名、主键、属性映射等元数据,缓存为
EntityTable。
通过@RegisterMapper注解,框架还支持"继承的通用接口"自动注册(hasRegisterMapper递归检查父接口),这正是细粒度接口组合能力的来源。
全局配置详解
通用 Mapper 的全部可配置项集中定义在 Config.java,前缀为mapper(PREFIX = "mapper")。以下参数均可在application.properties/application.yml中通过mapper.xxx配置:
| 配置项 | 默认值 | 说明 |
|---|---|---|
mappers | 空(Spring Boot 下自动注册tk.mybatis.mapper.common.Mapper) | 逗号分隔的通用 Mapper 接口全限定类名列表 |
IDENTITY/identity | MySQL | 主键自增回写 SQL,支持IdentityDialect内置方言(如 MYSQL),也可自定义 |
order/before | AFTER | SelectKey 回写主键的执行顺序,BEFORE或AFTER |
seqFormat | {0}.nextval | 序列获取规则,{0}为 SequenceName,针对 Oracle |
catalog | 空 | 全局 catalog,设置后 SQL 形如catalog.tablename |
schema | 空 | 全局 schema,与 catalog 同时设置时优先 catalog |
style | camelhump | 字段名转换风格:驼峰转下划线(camelhump)、normal、uppercase、lowercase等,非法值会抛出MapperException |
notEmpty | false | 对getAllIfColumnNode是否额外判断!= '' |
useSimpleType | true(3.5.0 后) | 是否使用简单类型 |
enumAsSimpleType | false | 枚举是否作为简单类型处理 |
simpleTypes | 空 | 注册新的基本类型,逗号分隔全限定类名 |
usePrimitiveType | false | 是否注册 8 种 Java 基本类型 |
enableMethodAnnotation | false | 是否支持方法上的注解 |
checkExampleEntityClass | false | 校验调用 Example 方法时Example(entityClass)与Mapper<EntityClass>是否一致 |
wrapKeyword | 空 | 关键字包装,mysql 可设为`{0}`,sqlserver 可设为[{0}],{0}代表列名 |
resolveClass | 空 | 自定义实体解析器(EntityResolve实现类) |
safeDelete | false | 安全删除:开启后不允许无条件的全表删除(如delete from table) |
safeUpdate | false | 安全更新:开启后不允许无条件的全表更新 |
logicDeleteByKey | true | 通过主键进行 select/update/delete 时是否拼接逻辑删除条件,设为 false 时不追加logicDeleteField = 0 |
useJavaType | false | 是否在 SQL 参数中设置 javaType,如{id, javaType=java.lang.Long} |
enableBaseResultMapFlag | false | 是否自动把 Mapper 接口中手写指定 resultType 的查询结果改为 resultMap |
这些参数的解析逻辑均可在 Config.setProperties 中找到,例如IDENTITY会先尝试通过IdentityDialect.getDatabaseDialect识别内置方言,识别失败则按自定义 SQL 处理;style非法时直接抛出异常。
Spring Boot 集成
仓库 spring-boot-starter 模块提供了mapper-spring-boot-starter与mapper-spring-boot-autoconfigure。其中 MapperProperties 直接继承Config并标注@ConfigurationProperties(prefix = "mapper"),其设计目的(见类注释)就是方便 IDE 自动提示mapper.开头的配置:
# 显式注册通用 Mapper 接口(不配置时默认自动注册 tk.mybatis.mapper.common.Mapper) mapper.mappers[0]=tk.mybatis.mapper.common.Mapper # 全局配置示例 mapper.style=camelhump mapper.safeDelete=true mapper.wrapKeyword=`{0}`MapperAutoConfiguration 负责自动装配SqlSessionFactory与SqlSessionTemplate,并在初始化阶段将MapperProperties绑定到MapperHelper。在 Spring Boot 项目中,通常只需:
- 引入
mapper-spring-boot-starter; - 实体类与 Mapper 接口同上(接口继承
tk.mybatis.mapper.common.Mapper或自定义组合); - 在启动类或配置类上使用
tk.mybatis.spring.annotation.MapperScan扫描 Mapper 接口(注意使用 tk 包下的注解,而非 MyBatis 官方注解)。
需要说明的是,仓库中spring-boot-starter模块 README(spring-boot-starter/README.md)展示的是较早期版本(1.2.x)的集成文档,其核心接入方式(starter 依赖 +mapper.前缀配置 + tk 包MapperScan)在当前版本中依然成立;但版本配套请以本文前述的"版本匹配说明"为准。
高级特性
主键策略:@KeySql
@KeySql 用于替换 JPA 中复杂的主键生成用法,支持四种策略(按优先级从高到低):
useGeneratedKeys():使用 JDBC 方式获取主键,优先级最高,设为 true 后不再校验其他配置;dialect():按配置的数据库方言取回主键(IdentityDialect),优先级第二;sql()/genSql():自定义取主键 SQL,或通过GenSql在初始化时生成 SQL;genId():纯 Java 方式生成主键(GenId实现类),可与发号器一类服务配合。
order()默认使用全局配置中的ORDER(BEFORE/AFTER)。仓库测试 base/genid 提供了SimpleGenId、UUIdGenId等实现示例。
逻辑删除:@LogicDelete
@LogicDelete 支持字段级逻辑删除,属性包括:
isDeletedValue():已删除标识,默认 1;notDeletedValue():未删除标识,默认 0;isNullForDeletedValue():以 null 作为已删除标识(优先级高于isDeletedValue);isNullForNotDeletedValue():以 null 作为未删除标识(优先级高于notDeletedValue)。
配合全局配置mapper.logicDeleteByKey=true(默认),通过主键的 select/update/delete 会自动拼接逻辑删除条件。
安全删除与安全更新
开启mapper.safeDelete=true后,框架禁止无条件全表删除。仓库测试 SafeDeleteByFieldTest 验证了四种危险场景都会抛出PersistenceException:
delete(new Country())(空条件对象);delete(null);deleteByExample(new Example(Country.class))(空 Example);deleteByExample(null)。
同理mapper.safeUpdate=true保护全表更新,对应测试见 SafeUpdateByFieldTest。
Example 条件查询
Example 是通用 Mapper 内置的条件查询对象,支持orderBy、selectProperties/excludeProperties(指定/排除查询列)、and()/or()分组条件、distinct、forUpdate等。其构造函数Example(Class<?> entityClass)默认exists=true;也可使用Example.builder(entityClass)链式构建,配合 Sqls 工具类生成orderBy、select等子句。配合 Weekend 模块,还可以用 Lambda 方式(WeekendSqls)书写类型安全的条件,避免字符串属性名拼写错误。
扩展方法(extra 模块)
extra 模块提供更多实用通用方法(extra/README.md 有介绍):
- 批量插入:
tk.mybatis.mapper.additional.insert.InsertListMapper,SQL 形如insert table(xxx) values (xxx), (xxx)...,适用于 MySQL、H2 等支持多值插入的数据库;Oracle 特殊批量插入使用INSERT ALL ... SELECT 1 FROM DUAL语法(见additional.dialect.oracle.InsertListMapper),由于语法限制暂不支持序列; - 空字段强制更新:
UpdateByPrimaryKeySelectiveForceMapper,解决UpdateByPrimaryKeySelective场景下空值也需要被设置的需求; - 按属性查询/删除:
SelectByPropertyMapper、DeleteByPropertyMapper; - 按 Id 列表操作:
SelectByIdListMapper、DeleteByIdListMapper; - 指定列查询:
SelectSpecifyColumnsMapper; - 批量更新 / 差异更新 / Upsert:
BatchUpdateMapper、UpdateByDifferMapper、UpsertMapper等; - 聚合查询:
AggregationMapper配合AggregateCondition实现分组聚合。
设计你自己的通用方法
仓库 README 特别强调:不要局限于已有通用方法,根据自己需要选择和设计的通用方法才更满足自己的需要。结合源码,自定义通用方法的标准路径是:
- 定义细粒度接口并标注
@RegisterMapper,方法上绑定自定义 Provider,例如:
@RegisterMapper public interface MySelectMapper<T> { @SelectProvider(type = MyProvider.class, method = "dynamicSQL") T mySelect(T record); }继承 MapperTemplate 编写 Provider,利用
EntityHelper获取实体元数据,用createSqlSource(ms, xmlSql)生成动态 SQL,其中模板方法签名需与接口方法一一对应(MapperHelper.fromMapperClasses会通过templateClass.getMethod(method.getName(), MappedStatement.class)校验,缺失会抛出异常)。将自定义接口注册进
Config.mappers或通过@RegisterMapper自动注册,即可像内置方法一样被 MapperHelper 拦截并替换 SQL。
仓库 hsqldb/HsqldbProvider 与 MultipleMapperProviderTest 都是自定义 Provider 的现成参考。
新项目建议
对于全新项目,README.md 建议关注新一代的mybatis-mapper:它完全作为 MyBatis 扩展存在,不修改 mybatis、mybatis-spring、mybatis-spring-boot-starter 任何代码,无需额外配置,可快速上手。若项目仍需停留在 Spring Boot 2.x / JDK 8 或 3.x / JDK 17,则按"版本匹配说明"选择 4.3.x 或 5.x 分支的通用 Mapper。
参考资源
- 仓库根 README.md:版本匹配说明、Maven 坐标与更新说明;
- core 模块:Config.java、MapperHelper.java、Example.java、注解包 annotation;
- base 模块:通用接口 common、Provider 实现 provider,以及 base 测试集(实体、Mapper、HSQLDB 建表脚本 CreateDB.sql);
- extra 模块:扩展通用方法及其测试;
- spring-boot-starter 模块:自动配置与
mapper.前缀属性绑定; - weekend 模块:Lambda 类型安全的条件查询封装。
- 后端
- ORM
- 数据库
【免费下载链接】Mapper
Mybatis Common Mapper - Easy to use
相关推荐
Spring Boot数据持久化完全指南:JPA、MyBatis与MyBatis-Plus对比
Spring Boot数据持久化完全指南:JPA、MyBatis与MyBatis Plus对比 在Spring Boot应用开发中, 数据持久化 是构建健壮企业
示例工程后端5 分钟上手 FreeCAD:免费 3D 参数化建模 CAD,从一张草图到能交付的零件
5 分钟上手 FreeCAD:免费 3D 参数化建模 CAD,从一张草图到能交付的零件 想给桌上那台设备配一个严丝合缝的定制支架,或者打个能正好卡进某个凹槽的
桌面应用3D建模图形学工业制造3小时快速上手:Mybatis Common Mapper与Spring Boot的终极集成指南
3小时快速上手:Mybatis Common Mapper与Spring Boot的终极集成指南 还在为Mybatis繁琐的配置而头疼?想要在Spring Bo
后端ORM数据库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考