tape-mybatis-generator-plugin
MyBatis 代码生成插件(基于 MyBatis Generator 1.4.1 开发,Maven 插件建议使用 1.4.0+)
功能特性
本插件为 MyBatis Generator 提供了以下增强功能:
- TapeMybatisGeneratorPlugin — 扩展 Mapper(
selectPrimaryKeyByExample、batchInsert)与 Example(分页、回收站筛选等) - TapeTableRepositoryGeneratorPlugin — 为非视图表生成 Repository 接口与实现,提供 CRUD、软删除与回收站
- TapeViewRepositoryGeneratorPlugin — 为视图表生成 View Repository 接口与实现,提供只读查询
视图表识别:通过 JDBC 元数据 tableType == "VIEW" 判断;非视图表与视图表由不同插件分别生成代码。
运行时依赖:生成的 Repository 使用 Spring @Repository、@Resource 及 SLF4J,使用方项目需引入对应依赖。
插件说明
TapeMybatisGeneratorPlugin
扩展 MyBatis Mapper 与 Example 类:
Mapper 接口 / XML
selectPrimaryKeyByExample(Example)— 按条件查询主键列表(支持 Example 分页limit)batchInsert(List<Model>)— 批量插入,返回影响行数
Mapper XML 动态 SQL
- 为
selectByExample、selectByExampleWithBLOBs、selectAll等查询追加limit片段(rows/offset)
TapeTableRepositoryGeneratorPlugin
为非视图表生成 Repository(类名后缀由 domainRepositoryType 控制,默认 Repository):
- 接口:
{facadeRepositoryPackage}.I{TableName}{domainRepositoryType} - 实现:
{domainRepositoryPackage}.{TableName}{domainRepositoryType}Impl
示例(默认后缀):IYourTableNameRepository、YourTableNameRepositoryImpl
生成的方法(均声明 throws Throwable):
| 方法 | 说明 |
|---|---|
trashById(long id) → int |
移入回收站(is_hidden=1) |
trashAll(Example) → int |
批量移入回收站;自动限定 is_delete=0 且 is_hidden=0 |
deleteById(long id, boolean release) → int |
release=false 软删;release=true 物理删除 |
deleteAll(Example, boolean release) → int |
release=false 仅软删回收站中记录(is_hidden=1);release=true 直接 deleteByExample |
recoverById(long id) → int |
从回收站恢复 |
recoverAll(Example) → int |
批量恢复;自动限定 is_delete=0 且 is_hidden=1 |
findAnyById(long id) → Model |
未删除(is_delete=0),不区分是否在回收站 |
findValidById(long id) → Model |
有效数据(is_hidden=0 且 is_delete=0) |
findTrashById(long id) → Model |
回收站数据(is_hidden=1 且 is_delete=0) |
findOne(Example) → Model |
单条(内部 usePage(1,1)) |
getList(Example) → List<Model> |
列表;按 resultType 过滤;含 BLOB 且分页时先查主键再查详情 |
count(Example) → long |
计数(含 resultType 过滤) |
countWithPage(Example) → long |
仅当 offset、rows 均已设置时调用 count,否则返回 0 |
insert(Model) → Model |
插入并返回带 GUID 的记录 |
batchInsert(List<Model>) → List<Model> |
批量插入并返回记录列表 |
update(Model) → int |
按主键更新(支持乐观锁) |
updateByExampleSelective(Model, Example) → int |
按条件选择性更新 |
TapeViewRepositoryGeneratorPlugin
为视图表生成 View Repository(类名后缀由 domainViewRepositoryType 控制,默认 Repository):
- 接口:
{facadeViewRepositoryPackage}.I{TableName}{domainViewRepositoryType} - 实现:
{domainViewRepositoryPackage}.{TableName}{domainViewRepositoryType}Impl
示例(默认后缀):IYourTableNameRepository、YourTableNameRepositoryImpl
生成的方法(均声明 throws Throwable):
| 方法 | 说明 |
|---|---|
findOne(Example) → Model |
单条 |
getList(Example) → List<Model> |
列表(支持 Example 分页;含 BLOB 时按 withBLOBs 选择查询方法) |
count(Example) → long |
计数 |
countWithPage(Example) → long |
行为同表 Repository |
Example 类增强(TapeMybatisGeneratorPlugin)
所有表/视图共有的字段与方法:
| 字段 / 方法 | 说明 |
|---|---|
offset、rows |
分页偏移与条数 |
startPageNum |
起始页码(默认 1,表级可覆盖) |
ignorePageSize |
usePage 时若 pageSize >= 该值则取消分页(默认 10000) |
maxPageSize |
usePage 时每页上限(默认 100) |
limit(rows) / limit(offset, rows) |
设置分页 |
limitOffset(offset, rows) |
设置 offset,rows 置为极大值(仅偏移) |
usePage(pageNum, pageSize) |
按页码计算 offset/rows |
getPageNum() / getPageSize() / getOffset() / getRows() |
读取分页状态;未设 rows 时 getPageSize() 返回 ignorePageSize |
getLimitString() / getWhereString() |
调试用 limit/where 字符串 |
cloneExample() |
克隆条件与分页状态 |
get/setMaxPageSize、get/setIgnorePageSize、get/setStartPageNum |
分页参数读写 |
仅非视图表额外支持:
| 字段 / 方法 | 说明 |
|---|---|
resultType |
null(默认,等同有效数据)、any、trash、valid |
setResultType / resultAny / resultTrash / resultValid |
设置筛选类型 |
isResultAny / isResultTrash / isResultValid |
isResultValid 在既非 any 也非 trash 时为 true(含 resultType==null) |
仅含 BLOB 列的表/视图:
| 字段 / 方法 | 说明 |
|---|---|
withBLOBs |
默认 true |
setWithBLOBs / isWithBLOBs |
是否查询 BLOB 列 |
getList / count 在表 Repository 中会根据 resultType 自动附加 is_hidden、is_delete 条件。
使用方法
1. 在 pom.xml 中配置插件
<build>
<finalName>application</finalName>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<configurationFile>src/main/resources/mybatis.generator.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<phase>deploy</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>com.iqudoo.framework</groupId>
<artifactId>tape-mybatis-generator-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<systemPath>${project.basedir}/src/lib/tape-mybatis-generator-plugin-1.0-SNAPSHOT.jar</systemPath>
<scope>system</scope>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
2. 在 mybatis.generator.xml 中配置插件
<context id="Mysql" targetRuntime="MyBatis3">
<property name="targetProject" value="src/main/java"/>
<property name="mapperPackage" value="com.iqudoo.platform.application.database.mapper"/>
<property name="modelPackage" value="com.iqudoo.platform.application.database.model"/>
<property name="facadeRepositoryPackage" value="com.iqudoo.platform.application.facade.repository"/>
<property name="domainRepositoryPackage" value="com.iqudoo.platform.application.domain.repository"/>
<property name="domainRepositoryType" value="Repository"/>
<property name="facadeViewRepositoryPackage" value="com.iqudoo.platform.application.facade.repoview"/>
<property name="domainViewRepositoryPackage" value="com.iqudoo.platform.application.domain.repoview"/>
<property name="domainViewRepositoryType" value="Repository"/>
<property name="guidGeneratorClass" value="com.iqudoo.framework.tape.modules.utils.SnowflakeUtil"/>
<property name="guidGeneratorCode" value="SnowflakeUtil.nextId()"/>
<property name="changeLogContextClassPackage" value="com.iqudoo.platform.application.domain.changeLog"/>
<property name="changeLogContextClassName" value="ChangeLogContext"/>
<property name="changeLogEnable" value="false"/>
<property name="slowQueryLoggerTime" value="300"/>
<property name="slowQueryLoggerLevel" value="error"/>
<property name="optimisticLockEnable" value="true"/>
<property name="ignorePageSize" value="10000"/>
<property name="startPageNum" value="1"/>
<property name="maxPageSize" value="100"/>
<plugin type="com.iqudoo.framework.mybatis.TapeMybatisGeneratorPlugin"/>
<plugin type="com.iqudoo.framework.mybatis.TapeTableRepositoryGeneratorPlugin"/>
<plugin type="com.iqudoo.framework.mybatis.TapeViewRepositoryGeneratorPlugin"/>
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<!-- 其他配置... -->
</context>
3. 全局配置参数说明
| 参数名 | 说明 | 默认值 | 必需 |
|---|---|---|---|
targetProject |
生成代码的目标项目路径 | src/main/java |
否 |
mapperPackage |
Mapper 接口包路径 | com.iqudoo.platform.application.database.mapper |
是 |
modelPackage |
Model 类包路径 | com.iqudoo.platform.application.database.model |
是 |
facadeRepositoryPackage |
表 Repository 接口包路径 | com.iqudoo.platform.application.facade.repository |
否 |
domainRepositoryPackage |
表 Repository 实现类包路径 | com.iqudoo.platform.application.domain.repository |
否 |
domainRepositoryType |
表 Repository 类名后缀 | Repository |
否 |
facadeViewRepositoryPackage |
视图 Repository 接口包路径 | com.iqudoo.platform.application.facade.repoview |
否 |
domainViewRepositoryPackage |
视图 Repository 实现类包路径 | com.iqudoo.platform.application.domain.repoview |
否 |
domainViewRepositoryType |
视图 Repository 类名后缀 | Repository |
否 |
guidGeneratorClass |
GUID 生成工具类(需 import) | com.iqudoo.framework.tape.modules.utils.SnowflakeUtil |
否 |
guidGeneratorCode |
GUID 生成表达式(写入生成代码) | SnowflakeUtil.nextId() |
否 |
changeLogContextClassPackage |
变更日志上下文包路径 | com.iqudoo.platform.application.domain.changeLog |
否 |
changeLogContextClassName |
变更日志上下文类名 | ChangeLogContext |
否 |
changeLogEnable |
变更日志开关 | false |
否 |
slowQueryLoggerTime |
慢查询阈值(毫秒) | 300 |
否 |
slowQueryLoggerLevel |
慢查询日志级别:error / warn / debug / info | error |
否 |
optimisticLockEnable |
乐观锁开关 | true |
否 |
ignorePageSize |
usePage 取消分页的 pageSize 阈值 |
10000 |
否 |
startPageNum |
分页起始页码 | 1 |
否 |
maxPageSize |
单页最大条数 | 100 |
否 |
4. TABLE 级配置
表级 <property> 优先于全局 <property>,未配置时回退到全局值。
| 参数名 | 说明 |
|---|---|
changeLogEnable |
变更日志开关 |
slowQueryLoggerTime |
慢查询阈值(毫秒) |
slowQueryLoggerLevel |
慢查询日志级别 |
optimisticLockEnable |
乐观锁开关 |
ignorePageSize |
取消分页阈值 |
startPageNum |
起始页码 |
maxPageSize |
单页最大条数 |
示例:
<table tableName="your_table_name"
domainObjectName="YourTableName"
enableInsert="true"
enableDeleteByPrimaryKey="true"
enableUpdateByPrimaryKey="true"
enableCountByExample="true"
enableUpdateByExample="true"
enableDeleteByExample="true"
enableSelectByExample="true"
selectByExampleQueryId="false">
<property name="useActualColumnNames" value="false"/>
<property name="changeLogEnable" value="false"/>
<property name="slowQueryLoggerTime" value="200"/>
<property name="slowQueryLoggerLevel" value="warn"/>
<property name="optimisticLockEnable" value="false"/>
<property name="ignorePageSize" value="10000"/>
<property name="startPageNum" value="1"/>
<property name="maxPageSize" value="100"/>
</table>
变更日志监听
changeLogEnable=true 时,Repository 实现会调用 ChangeLogContext.addLog。使用方需提供如下静态方法:
public class ChangeLogContext {
public static void addLog(String tableName, String eventType, Long dataGuid,
Map<String, Object[]> fieldChanges) {
// 自行实现
}
}
eventType 取值:
| eventType | 触发操作 |
|---|---|
insert |
insert |
batchInsert |
batchInsert |
update |
update |
updateByExampleSelective |
updateByExampleSelective |
deleteById |
deleteById(软删) |
deleteAll |
deleteAll(软删) |
trashById |
trashById |
trashAll |
trashAll |
recoverById |
recoverById |
recoverAll |
recoverAll |
fieldChanges 中 Object[] 为 [旧值, 新值];插入/删除类事件通常为空 Map。
数据库表结构要求
标准表结构模板
使用完整 Repository 功能(软删除、回收站、乐观锁)时,表需包含以下标准字段:
DROP TABLE IF EXISTS `your_table_name`;
CREATE TABLE `your_table_name` (
`guid` bigint(0) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'GUID',
-- 业务字段
`is_hidden` int(0) NOT NULL DEFAULT 0 COMMENT '隐藏标志',
`is_delete` int(0) NOT NULL DEFAULT 0 COMMENT '删除标志',
`delete_token` varchar(32) NULL DEFAULT '' COMMENT '删除令牌',
`data_version` int(0) NOT NULL DEFAULT 0 COMMENT '数据版本',
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
`update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '更新时间',
PRIMARY KEY (`guid`) USING BTREE,
KEY `idx_common_query` (`is_hidden`, `is_delete`, `create_time` desc, `guid`) USING BTREE
) ENGINE = InnoDB COMMENT = '你的表格备注'
ROW_FORMAT = Dynamic;
索引优化指南
唯一键索引(含 delete_token 以支持回收站后重建):
UNIQUE KEY `idx_your_unique_key` (
`your_unique_key`,
`delete_token`
) USING BTREE
查询索引:
KEY `idx_your_query_case` (
`is_hidden`, `is_delete`,
`create_time` desc,
`guid`
) USING BTREE
标准字段说明:
| 字段 | 说明 |
|---|---|
guid |
主键,bigint UNSIGNED |
is_hidden |
回收站标志(1 = 在回收站) |
is_delete |
软删除标志 |
delete_token |
删除令牌(有效数据为 VALID,进回收站后变更) |
data_version |
乐观锁版本号 |
create_time / update_time |
插入时自动设置 |
视图表
视图表无需上述标准字段,仅需业务列;由 TapeViewRepositoryGeneratorPlugin 生成只读 Repository。
在 mybatis.generator.xml 中配置表
<table tableName="your_table_name"
domainObjectName="YourTableName"
enableInsert="true"
enableDeleteByPrimaryKey="true"
enableUpdateByPrimaryKey="true"
enableCountByExample="true"
enableUpdateByExample="true"
enableDeleteByExample="true"
enableSelectByExample="true"
selectByExampleQueryId="false">
<property name="useActualColumnNames" value="false"/>
</table>
非视图表注意事项
- 主键:必须有名为
guid的主键,类型bigint UNSIGNED。 - 视图表判定:JDBC
tableType为VIEW时不会生成表 Repository,改由视图插件处理。 - 分页:Example 支持
usePage()/limit();pageSize >= ignorePageSize时不加分页。 - 乐观锁:
update使用data_version;optimisticLockEnable=false时不校验版本。 - 软删除:
deleteById/deleteAll默认软删(is_delete=1);release=true为物理删除。 - 回收站:
trash*设置is_hidden=1;recover*恢复为is_hidden=0、delete_token=VALID。 - 批量删除:
deleteAll(release=false)仅作用于已在回收站的记录。 - 自动字段:
insert/batchInsert自动设置guid(guidGeneratorCode)、is_delete=0、is_hidden=0、delete_token=VALID、data_version=1、时间戳等。 - BLOB:含 BLOB 列时,
getList分页查询先selectPrimaryKeyByExample再按 GUID 拉取详情;可通过withBLOBs控制是否查询 BLOB 列。