Compare commits
24 Commits
e6ccd3bc34
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b827f0e4d0 | ||
|
|
45f5300e42 | ||
|
|
c27a2433be | ||
|
|
88fa1c88dd | ||
|
|
748ebad0c4 | ||
|
|
4d7e0eab85 | ||
|
|
ef0704a45e | ||
|
|
908d7333ab | ||
|
|
b6e4ab65e7 | ||
|
|
94360e50b9 | ||
|
|
ac8bd3c556 | ||
|
|
6423803562 | ||
|
|
a73e969431 | ||
|
|
ac547d2a57 | ||
|
|
e547f645a6 | ||
|
|
c048da1faf | ||
|
|
b85966c535 | ||
|
|
0bea5abfb6 | ||
|
|
885f823203 | ||
|
|
dc7ccf905f | ||
|
|
abfab32498 | ||
|
|
6ecdf66eeb | ||
|
|
4bddff2de9 | ||
|
|
a2e1fdd8e3 |
427
README.md
427
README.md
@@ -1,89 +1,126 @@
|
||||
# tape-mybatis-generator-plugin
|
||||
> MyBatis 代码生成插件
|
||||
|
||||
> MyBatis 代码生成插件(基于 MyBatis Generator **1.4.1** 开发,Maven 插件建议使用 **1.4.0+**)
|
||||
|
||||
## 功能特性
|
||||
|
||||
本插件为 MyBatis Generator 提供了以下增强功能:
|
||||
|
||||
1. **TapeMybatisGeneratorPlugin** - 扩展 MyBatis Mapper,添加 `selectPrimaryKeyByExample` 方法,支持分页查询主键列表
|
||||
2. **TapeRepositoryGeneratorPlugin** - 为非视图表自动生成 Repository 接口和实现类,提供完整的 CRUD 和软删除功能
|
||||
3. **TapeRepoviewGeneratorPlugin** - 为视图表自动生成 RepoView 接口和实现类,提供查询功能
|
||||
4. **分页支持** - 为 Example 类自动添加分页相关字段和方法(offset、rows、usePage、limit 等)
|
||||
1. **TapeMybatisGeneratorPlugin** — 扩展 Mapper(`selectPrimaryKeyByExample`、`batchInsert`)与 Example(分页、回收站筛选等)
|
||||
2. **TapeTableRepositoryGeneratorPlugin** — 为非视图表生成 Repository 接口与实现,提供 CRUD、软删除与回收站
|
||||
3. **TapeViewRepositoryGeneratorPlugin** — 为视图表生成 View Repository 接口与实现,提供只读查询
|
||||
|
||||
**视图表识别**:通过 JDBC 元数据 `tableType == "VIEW"` 判断;非视图表与视图表由不同插件分别生成代码。
|
||||
|
||||
**运行时依赖**:生成的 Repository 使用 Spring `@Repository`、`@Resource` 及 SLF4J,使用方项目需引入对应依赖。
|
||||
|
||||
## 插件说明
|
||||
|
||||
### TapeMybatisGeneratorPlugin
|
||||
扩展 MyBatis Mapper,添加以下功能:
|
||||
- 在 Mapper 接口中添加 `selectPrimaryKeyByExample` 方法
|
||||
- 在 Mapper XML 中生成对应的 SQL 查询语句
|
||||
|
||||
### TapeRepositoryGeneratorPlugin
|
||||
为非视图表生成 Repository 层代码:
|
||||
- **接口位置**: `{facadeRepositoryPackage}.I{TableName}Repository`
|
||||
- **实现类位置**: `{domainRepositoryPackage}.{TableName}RepositoryImpl`
|
||||
- **视图表过滤**: 根据 `viewKeyWords` 配置自动识别并跳过视图表
|
||||
扩展 MyBatis Mapper 与 Example 类:
|
||||
|
||||
**生成的方法**:
|
||||
- `trashById(long id)` - 移动到回收站(单个)
|
||||
- `trashAll({Example} example)` - 移动到回收站(批量)
|
||||
- `deleteById(long id, boolean release)` - 删除(单个,支持物理删除)
|
||||
- `deleteAll({Example} example, boolean release)` - 删除(批量,支持物理删除)
|
||||
- `recoverById(long id)` - 从回收站恢复(单个)
|
||||
- `recoverAll({Example} example)` - 从回收站恢复(批量)
|
||||
- `findAnyById(long id)` - 查找(不区分有效/回收站)
|
||||
- `findValidById(long id)` - 查找有效记录(单个)
|
||||
- `findTrashById(long id)` - 查找回收站记录(单个)
|
||||
- `findValidOne({Example} example)` - 查找有效记录(单个,支持条件)
|
||||
- `findTrashOne({Example} example)` - 查找回收站记录(单个,支持条件)
|
||||
- `getValidList({Example} example)` - 获取有效记录列表(支持分页)
|
||||
- `getTrashList({Example} example)` - 获取回收站记录列表(支持分页)
|
||||
- `countByValid({Example} example)` - 统计有效记录数
|
||||
- `countByTrash({Example} example)` - 统计回收站记录数
|
||||
- `insert({Model} record)` - 插入记录(自动生成 GUID、设置默认值)
|
||||
- `updateByExampleSelective({Model} record, {Example} example)` - 按条件更新记录
|
||||
- `update({Model} record)` - 更新记录(支持乐观锁)
|
||||
**Mapper 接口 / XML**
|
||||
|
||||
### TapeRepoviewGeneratorPlugin
|
||||
为视图表生成 RepoView 层代码:
|
||||
- **接口位置**: `{facadeRepoviewPackage}.I{TableName}Repo`
|
||||
- **实现类位置**: `{domainRepoviewPackage}.{TableName}RepoImpl`
|
||||
- **视图表识别**: 仅处理包含 `viewKeyWords` 关键字的表
|
||||
- `selectPrimaryKeyByExample(Example)` — 按条件查询主键列表(支持 Example 分页 `limit`)
|
||||
- `batchInsert(List<Model>)` — 批量插入,返回影响行数
|
||||
|
||||
**生成的方法**:
|
||||
- `findOne({Example} example)` - 查找单条记录
|
||||
- `getList({Example} example)` - 获取记录列表(支持分页)
|
||||
- `count({Example} example)` - 统计记录数
|
||||
**Mapper XML 动态 SQL**
|
||||
|
||||
### 其他功能
|
||||
通过 `TapeMybatisGeneratorPlugin` 为所有 Example 类添加支持:
|
||||
- 为 `selectByExample`、`selectByExampleWithBLOBs`、`selectAll` 等查询追加 `limit` 片段(`rows` / `offset`)
|
||||
|
||||
**添加的字段**:
|
||||
- `offset` - 偏移量
|
||||
- `rows` - 每页数量
|
||||
- `minPageNum` - 最小页码(默认 1)
|
||||
- `ignorePageSize` - 忽略分页数量(默认 10000)每页数量大于10000时,忽略分页
|
||||
- `defaultPageSize` - 默认每页数量(默认 20)
|
||||
- `maxPageSize` - 最大每页数量(默认 100)
|
||||
- `withBLOBs` - 是否返回BLOBs列的数据
|
||||
### TapeTableRepositoryGeneratorPlugin
|
||||
|
||||
**添加的方法**:
|
||||
- `limit(int rows)` - 设置每页数量
|
||||
- `limit(int offset, int rows)` - 设置偏移量和每页数量
|
||||
- `usePage(int pageNum, int pageSize)` - 使用页码和每页数量(自动计算 offset)
|
||||
- `getPageNum()` - 获取当前页码
|
||||
- `getPageSize()` - 获取当前每页数量
|
||||
- `setWithBLOBs(boolean withBLOBs)` - 设置是否返回BLOBs列的数据
|
||||
- `isWithBLOBs()` - 是否返回BLOBs列的数据
|
||||
为非视图表生成 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` 中配置插件
|
||||
|
||||
```xml
|
||||
<build>
|
||||
<finalName>application</finalName>
|
||||
<plugins>
|
||||
<!-- your other plugins -->
|
||||
<!-- add mybatis plugin -->
|
||||
<plugin>
|
||||
<groupId>org.mybatis.generator</groupId>
|
||||
<artifactId>mybatis-generator-maven-plugin</artifactId>
|
||||
@@ -126,94 +163,195 @@
|
||||
|
||||
```xml
|
||||
<context id="Mysql" targetRuntime="MyBatis3">
|
||||
<!-- 配置属性 -->
|
||||
<property name="viewKeyWords" value="VIEW_,V_"/>
|
||||
<property name="targetProject" value="src/main/java"/>
|
||||
<property name="modelPackage" value="com.iqudoo.platform.application.database.model"/>
|
||||
<property name="mapperPackage" value="com.iqudoo.platform.application.database.mapper"/>
|
||||
<property name="facadeRepositoryPackage" value="com.iqudoo.platform.application.facade.repository"/>
|
||||
<property name="domainRepositoryPackage" value="com.iqudoo.platform.application.domain.repository"/>
|
||||
<property name="facadeRepoviewPackage" value="com.iqudoo.platform.application.facade.repoview"/>
|
||||
<property name="domainRepoviewPackage" value="com.iqudoo.platform.application.domain.repoview"/>
|
||||
<property name="snowflakeUtilClass" value="com.iqudoo.framework.tape.modules.utils.SnowflakeUtil"/>
|
||||
<property name="snowflakeUtilGenId" value="SnowflakeUtil.nextId()"/>
|
||||
<property name="slowQueryLoggerTime" value="300"/>
|
||||
<property name="ignorePageSize" value="10000"/>
|
||||
<property name="defaultPageSize" value="20"/>
|
||||
<property name="startPage" value="1"/>
|
||||
<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.TapeRepositoryGeneratorPlugin"/>
|
||||
<plugin type="com.iqudoo.framework.mybatis.TapeRepoviewGeneratorPlugin"/>
|
||||
<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. 配置参数说明
|
||||
### 3. 全局配置参数说明
|
||||
|
||||
| 参数名 | 说明 | 默认值 | 必需 |
|
||||
|--------|---------------------|---------------------------------------------------------|------|
|
||||
| `viewKeyWords` | 视图表关键字(逗号分隔,不区分大小写) | `VIEW_,V_` | 否 |
|
||||
| `targetProject` | 生成代码的目标项目路径 | `src/main/java` | 否 |
|
||||
| `modelPackage` | Model 类的包路径 | `com.iqudoo.platform.application.database.model` | 是 |
|
||||
| `mapperPackage` | Mapper 接口的包路径 | `com.iqudoo.platform.application.database.mapper` | 是 |
|
||||
| `facadeRepositoryPackage` | Repository 接口的包路径 | `com.iqudoo.platform.application.facade.repository` | 否 |
|
||||
| `domainRepositoryPackage` | Repository 实现类的包路径 | `com.iqudoo.platform.application.domain.repository` | 否 |
|
||||
| `facadeRepoviewPackage` | RepoView 接口的包路径 | `com.iqudoo.platform.application.facade.repoview` | 否 |
|
||||
| `snowflakeUtilClass` | 雪花算法ID生成工具类 | `com.iqudoo.framework.tape.modules.utils.SnowflakeUtil` | 否 |
|
||||
| `snowflakeUtilGenId` | 雪花算法ID生成方法 | `SnowflakeUtil.nextId()` | 否 |
|
||||
| `slowQueryLoggerTime` | 慢查询日志时间阈值 | `200` | 否 |
|
||||
| `ignorePageSize` | 忽略分页阈值 | `10000` | 否 |
|
||||
| `defaultPageSize` | 默认分页数量 | `20` | 否 |
|
||||
| `startPage` | 开始页码 | `1` | 否 |
|
||||
| 参数名 | 说明 | 默认值 | 必需 |
|
||||
|--------|------|--------|------|
|
||||
| `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` | 否 |
|
||||
|
||||
**视图表识别规则**:
|
||||
- 表名包含 `viewKeyWords` 中任一关键字的表将被识别为视图表,大小写不敏感
|
||||
- 视图表会生成 RepoView,不会生成 Repository
|
||||
- 非视图表会生成 Repository,不会生成 RepoView
|
||||
### 4. TABLE 级配置
|
||||
|
||||
表级 `<property>` 优先于全局 `<property>`,未配置时回退到全局值。
|
||||
|
||||
| 参数名 | 说明 |
|
||||
|--------|------|
|
||||
| `changeLogEnable` | 变更日志开关 |
|
||||
| `slowQueryLoggerTime` | 慢查询阈值(毫秒) |
|
||||
| `slowQueryLoggerLevel` | 慢查询日志级别 |
|
||||
| `optimisticLockEnable` | 乐观锁开关 |
|
||||
| `ignorePageSize` | 取消分页阈值 |
|
||||
| `startPageNum` | 起始页码 |
|
||||
| `maxPageSize` | 单页最大条数 |
|
||||
|
||||
示例:
|
||||
|
||||
```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"/>
|
||||
<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`。使用方需提供如下静态方法:
|
||||
|
||||
```java
|
||||
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 功能(软删除、回收站等),表结构需要包含以下标准字段:
|
||||
使用完整 Repository 功能(软删除、回收站、乐观锁)时,表需包含以下标准字段:
|
||||
|
||||
```sql
|
||||
```mysql
|
||||
DROP TABLE IF EXISTS `your_table_name`;
|
||||
CREATE TABLE `your_table_name` (
|
||||
`guid` bigint(0) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'GUID',
|
||||
-- ----------------------------
|
||||
-- add your table other table field
|
||||
-- ----------------------------
|
||||
`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
|
||||
) ENGINE = InnoDB COMMENT = '你的表格备注' ROW_FORMAT = Dynamic;
|
||||
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;
|
||||
```
|
||||
|
||||
**必需字段说明**:
|
||||
- `guid` - 主键,类型为 `bigint UNSIGNED`
|
||||
- `is_hidden` - 隐藏标志,用于回收站功能
|
||||
- `is_delete` - 删除标志,用于软删除功能
|
||||
- `delete_token` - 删除令牌,用于标识删除状态
|
||||
- `data_version` - 数据版本,用于乐观锁
|
||||
- `create_time` - 创建时间,自动设置
|
||||
- `update_time` - 更新时间,自动更新
|
||||
### 索引优化指南
|
||||
|
||||
### 视图表结构
|
||||
唯一键索引(含 `delete_token` 以支持回收站后重建):
|
||||
|
||||
视图表不需要上述标准字段,只需要包含业务字段即可。
|
||||
```sql
|
||||
UNIQUE KEY `idx_your_unique_key` (
|
||||
`your_unique_key`,
|
||||
`delete_token`
|
||||
) USING BTREE
|
||||
```
|
||||
|
||||
查询索引:
|
||||
|
||||
```sql
|
||||
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` 中配置表
|
||||
|
||||
```xml
|
||||
<!-- 标准表配置 -->
|
||||
<table tableName="your_table_name"
|
||||
domainObjectName="YourTableName"
|
||||
enableInsert="true"
|
||||
@@ -226,31 +364,16 @@ CREATE TABLE `your_table_name` (
|
||||
selectByExampleQueryId="false">
|
||||
<property name="useActualColumnNames" value="false"/>
|
||||
</table>
|
||||
|
||||
<!-- 视图表配置(表名包含 VIEW_ 或 V_ 前缀,大小写不敏感) -->
|
||||
<table tableName="v_your_view_name"
|
||||
domainObjectName="ViewYourViewName"
|
||||
enableInsert="false"
|
||||
enableDeleteByPrimaryKey="false"
|
||||
enableUpdateByPrimaryKey="false"
|
||||
enableCountByExample="true"
|
||||
enableUpdateByExample="false"
|
||||
enableDeleteByExample="false"
|
||||
enableSelectByExample="true"
|
||||
selectByExampleQueryId="false">
|
||||
<property name="useActualColumnNames" value="false"/>
|
||||
<generatedKey column="guid" sqlStatement="JDBC" identity="false"/>
|
||||
</table>
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
## 非视图表注意事项
|
||||
|
||||
1. **主键要求**:表必须有一个主键字段,且字段名为 `guid`,类型为 `bigint UNSIGNED`
|
||||
2. **视图表识别**:视图表通过表名中的关键字识别,默认关键字为 `view_` 和 `v_` 不区分大小写
|
||||
3. **分页功能**:所有 Example 类都自动包含分页功能,可通过 `usePage()` 方法使用
|
||||
4. **乐观锁**:更新操作使用 `data_version` 字段实现乐观锁,更新时需要传入正确的版本号
|
||||
5. **软删除**:删除操作默认是软删除(设置 `is_delete` 标志),可通过 `release=true` 参数执行物理删除
|
||||
6. **回收站**:通过 `is_hidden` 字段实现回收站功能,`trash` 方法将记录移动到回收站,`recover` 方法恢复记录
|
||||
7. **自动字段**:插入记录时,插件会自动设置 `guid`(使用雪花算法)、`is_delete`、`is_hidden`、`delete_token`、`data_version`、`create_time`、`update_time` 等字段
|
||||
8. **BLOB 字段支持**:如果表包含 BLOB 字段,插件会自动使用 `selectByExampleWithBLOBs` 和 `updateByExampleWithBLOBs` 方法
|
||||
9. **MyBatis Generator 版本**:本插件基于 MyBatis Generator 1.4.1 开发,建议使用 1.4.0 或更高版本
|
||||
1. **主键**:必须有名为 `guid` 的主键,类型 `bigint UNSIGNED`。
|
||||
2. **视图表判定**:JDBC `tableType` 为 `VIEW` 时不会生成表 Repository,改由视图插件处理。
|
||||
3. **分页**:Example 支持 `usePage()` / `limit()`;`pageSize >= ignorePageSize` 时不加分页。
|
||||
4. **乐观锁**:`update` 使用 `data_version`;`optimisticLockEnable=false` 时不校验版本。
|
||||
5. **软删除**:`deleteById` / `deleteAll` 默认软删(`is_delete=1`);`release=true` 为物理删除。
|
||||
6. **回收站**:`trash*` 设置 `is_hidden=1`;`recover*` 恢复为 `is_hidden=0`、`delete_token=VALID`。
|
||||
7. **批量删除**:`deleteAll(release=false)` 仅作用于已在回收站的记录。
|
||||
8. **自动字段**:`insert` / `batchInsert` 自动设置 `guid`(`guidGeneratorCode`)、`is_delete=0`、`is_hidden=0`、`delete_token=VALID`、`data_version=1`、时间戳等。
|
||||
9. **BLOB**:含 BLOB 列时,`getList` 分页查询先 `selectPrimaryKeyByExample` 再按 GUID 拉取详情;可通过 `withBLOBs` 控制是否查询 BLOB 列。
|
||||
|
||||
Binary file not shown.
@@ -2,6 +2,7 @@ package com.iqudoo.framework.mybatis;
|
||||
|
||||
import com.iqudoo.framework.mybatis.utils.ElementTools;
|
||||
import com.iqudoo.framework.mybatis.utils.FormatTools;
|
||||
import org.mybatis.generator.api.IntrospectedColumn;
|
||||
import org.mybatis.generator.api.IntrospectedTable;
|
||||
import org.mybatis.generator.api.PluginAdapter;
|
||||
import org.mybatis.generator.api.dom.java.*;
|
||||
@@ -9,93 +10,148 @@ import org.mybatis.generator.api.dom.xml.Attribute;
|
||||
import org.mybatis.generator.api.dom.xml.Document;
|
||||
import org.mybatis.generator.api.dom.xml.TextElement;
|
||||
import org.mybatis.generator.api.dom.xml.XmlElement;
|
||||
import org.mybatis.generator.config.Context;
|
||||
import org.mybatis.generator.config.TableConfiguration;
|
||||
import org.mybatis.generator.internal.util.StringUtility;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class TapeMybatisGeneratorPlugin extends PluginAdapter {
|
||||
|
||||
private final static int DEFAULT_START_PAGE = 1;
|
||||
private final static int DEFAULT_PAGE_SIZE = 20;
|
||||
private final static int DEFAULT_IGNORE_PAGE_SIZE = 10000;
|
||||
private int startPage = DEFAULT_START_PAGE;
|
||||
private int defaultPageSize = DEFAULT_PAGE_SIZE;
|
||||
private int ignorePageSize = DEFAULT_IGNORE_PAGE_SIZE;
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
super.setProperties(properties);
|
||||
if (StringUtility.stringHasValue(properties.getProperty("startPage"))) {
|
||||
try {
|
||||
startPage = Integer.parseInt(properties.getProperty("startPage"));
|
||||
} catch (Throwable ignored) {
|
||||
startPage = DEFAULT_START_PAGE;
|
||||
}
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("defaultPageSize"))) {
|
||||
try {
|
||||
defaultPageSize = Integer.parseInt(properties.getProperty("defaultPageSize"));
|
||||
} catch (Throwable ignored) {
|
||||
defaultPageSize = DEFAULT_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("ignorePageSize"))) {
|
||||
try {
|
||||
ignorePageSize = Integer.parseInt(properties.getProperty("ignorePageSize"));
|
||||
} catch (Throwable ignored) {
|
||||
ignorePageSize = DEFAULT_IGNORE_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
private int startPageNum = 1;
|
||||
private int maxPageSize = 100;
|
||||
private int ignorePageSize = 10000;
|
||||
|
||||
@Override
|
||||
public boolean validate(List<String> list) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContext(Context context) {
|
||||
super.setContext(context);
|
||||
resolveConfiguration();
|
||||
}
|
||||
|
||||
private void resolveConfiguration() {
|
||||
startPageNum = intConfig("startPageNum", startPageNum);
|
||||
ignorePageSize = intConfig("ignorePageSize", ignorePageSize);
|
||||
maxPageSize = intConfig("maxPageSize", maxPageSize);
|
||||
}
|
||||
|
||||
private int intConfig(String key, int defaultValue) {
|
||||
String v = properties.getProperty(key);
|
||||
if (!StringUtility.stringHasValue(v) && context != null) {
|
||||
v = context.getProperty(key);
|
||||
}
|
||||
if (!StringUtility.stringHasValue(v)) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(v.trim());
|
||||
} catch (Throwable ignored) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
private int getIgnorePageSize(IntrospectedTable introspectedTable) {
|
||||
return getTableInt(introspectedTable, "ignorePageSize", ignorePageSize);
|
||||
}
|
||||
|
||||
public int getMaxPageSize(IntrospectedTable introspectedTable) {
|
||||
return getTableInt(introspectedTable, "maxPageSize", maxPageSize);
|
||||
}
|
||||
|
||||
public int getStartPageNum(IntrospectedTable introspectedTable) {
|
||||
return getTableInt(introspectedTable, "startPageNum", startPageNum);
|
||||
}
|
||||
|
||||
// ====================== 统一 Table 属性获取(你全类都能用) ======================
|
||||
private String getTableProperty(IntrospectedTable introspectedTable, String propName, String defaultValue) {
|
||||
try {
|
||||
TableConfiguration tc = introspectedTable.getTableConfiguration();
|
||||
String v = tc.getProperty(propName);
|
||||
if (StringUtility.stringHasValue(v)) {
|
||||
return v.trim();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private boolean getTableBool(IntrospectedTable introspectedTable, String propName, boolean defaultValue) {
|
||||
String v = getTableProperty(introspectedTable, propName, String.valueOf(defaultValue));
|
||||
try {
|
||||
return Boolean.parseBoolean(v);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
private int getTableInt(IntrospectedTable introspectedTable, String propName, int defaultValue) {
|
||||
String v = getTableProperty(introspectedTable, propName, String.valueOf(defaultValue));
|
||||
try {
|
||||
return Integer.parseInt(v);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
@Override
|
||||
public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
|
||||
PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper();
|
||||
// 添加 minPageNum、defaultPageSize、maxPageSize、ignorePageSize 字段
|
||||
topLevelClass.addImportedType(new FullyQualifiedJavaType("java.util.Objects"));
|
||||
|
||||
FullyQualifiedJavaType integerType = new FullyQualifiedJavaType("java.lang.Integer");
|
||||
FullyQualifiedJavaType booleanType = new FullyQualifiedJavaType("java.lang.Boolean");
|
||||
FullyQualifiedJavaType stringType = new FullyQualifiedJavaType("java.lang.String");
|
||||
|
||||
String domainObjectName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
|
||||
String exampleClassName = domainObjectName + "Example";
|
||||
|
||||
|
||||
if (!ElementTools.isViewTable(introspectedTable)) {
|
||||
// any, trash, valid
|
||||
Field resultType = ElementTools.generateField(
|
||||
"resultType",
|
||||
JavaVisibility.PROTECTED,
|
||||
stringType,
|
||||
"null"
|
||||
);
|
||||
topLevelClass.addField(resultType);
|
||||
}
|
||||
|
||||
// 添加 startPageNum、maxPageSize、ignorePageSize 字段
|
||||
Field maxPageSizeField = ElementTools.generateField(
|
||||
"maxPageSize",
|
||||
JavaVisibility.PROTECTED,
|
||||
integerWrapper,
|
||||
"100"
|
||||
integerType,
|
||||
getMaxPageSize(introspectedTable) + ""
|
||||
);
|
||||
topLevelClass.addField(maxPageSizeField);
|
||||
|
||||
Field ignorePageSizeField = ElementTools.generateField(
|
||||
"ignorePageSize",
|
||||
JavaVisibility.PROTECTED,
|
||||
integerWrapper,
|
||||
this.ignorePageSize + ""
|
||||
integerType,
|
||||
getIgnorePageSize(introspectedTable) + ""
|
||||
);
|
||||
topLevelClass.addField(ignorePageSizeField);
|
||||
|
||||
Field defaultPageSizeField = ElementTools.generateField(
|
||||
"defaultPageSize",
|
||||
Field startPageNumField = ElementTools.generateField(
|
||||
"startPageNum",
|
||||
JavaVisibility.PROTECTED,
|
||||
integerWrapper,
|
||||
defaultPageSize + ""
|
||||
integerType,
|
||||
getStartPageNum(introspectedTable) + ""
|
||||
);
|
||||
topLevelClass.addField(defaultPageSizeField);
|
||||
|
||||
Field minPageNumField = ElementTools.generateField(
|
||||
"minPageNum",
|
||||
JavaVisibility.PROTECTED,
|
||||
integerWrapper,
|
||||
startPage + ""
|
||||
);
|
||||
topLevelClass.addField(minPageNumField);
|
||||
topLevelClass.addField(startPageNumField);
|
||||
|
||||
// 添加offset和rows字段
|
||||
Field offsetField = ElementTools.generateField(
|
||||
"offset",
|
||||
JavaVisibility.PROTECTED,
|
||||
integerWrapper,
|
||||
integerType,
|
||||
"null"
|
||||
);
|
||||
topLevelClass.addField(offsetField);
|
||||
@@ -103,7 +159,7 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
|
||||
Field rowsField = ElementTools.generateField(
|
||||
"rows",
|
||||
JavaVisibility.PROTECTED,
|
||||
integerWrapper,
|
||||
integerType,
|
||||
"null"
|
||||
);
|
||||
topLevelClass.addField(rowsField);
|
||||
@@ -114,7 +170,7 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
|
||||
Field withBLOBsField = ElementTools.generateField(
|
||||
"withBLOBs",
|
||||
JavaVisibility.PROTECTED,
|
||||
new FullyQualifiedJavaType("java.lang.Boolean"),
|
||||
booleanType,
|
||||
"true"
|
||||
);
|
||||
topLevelClass.addField(withBLOBsField);
|
||||
@@ -127,7 +183,6 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, isWithBLOBsMethod);
|
||||
}
|
||||
|
||||
|
||||
// 增加getter && setter 方法
|
||||
Method mSetMaxPageSize = ElementTools.generateSetterMethod(maxPageSizeField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mSetMaxPageSize);
|
||||
@@ -141,102 +196,196 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
|
||||
Method mGetIgnorePageSize = ElementTools.generateGetterMethod(ignorePageSizeField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mGetIgnorePageSize);
|
||||
|
||||
Method mSetDefaultPageSize = ElementTools.generateSetterMethod(defaultPageSizeField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mSetDefaultPageSize);
|
||||
Method mSetStartPageNum = ElementTools.generateSetterMethod(startPageNumField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mSetStartPageNum);
|
||||
|
||||
Method mGetDefaultPageSize = ElementTools.generateGetterMethod(defaultPageSizeField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mGetDefaultPageSize);
|
||||
Method mGetStartPageNum = ElementTools.generateGetterMethod(startPageNumField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mGetStartPageNum);
|
||||
|
||||
Method mSetMinPageNum = ElementTools.generateSetterMethod(minPageNumField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mSetMinPageNum);
|
||||
|
||||
Method mGetMinPageNum = ElementTools.generateGetterMethod(minPageNumField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mGetMinPageNum);
|
||||
if (!ElementTools.isViewTable(introspectedTable)) {
|
||||
|
||||
Method mSetOffset = ElementTools.generateSetterMethod(offsetField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mSetOffset);
|
||||
// setResultType
|
||||
Method setResultType = ElementTools.generateMethod(
|
||||
"setResultType",
|
||||
JavaVisibility.PUBLIC,
|
||||
topLevelClass.getType(),
|
||||
new Parameter(stringType, "type")
|
||||
);
|
||||
setResultType = ElementTools.generateMethodBody(
|
||||
setResultType,
|
||||
"this.resultType = type;",
|
||||
"return this;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, setResultType);
|
||||
|
||||
Method mGetOffset = ElementTools.generateGetterMethod(offsetField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mGetOffset);
|
||||
// resultValid
|
||||
Method resultValid = ElementTools.generateMethod(
|
||||
"resultValid",
|
||||
JavaVisibility.PUBLIC,
|
||||
topLevelClass.getType()
|
||||
);
|
||||
resultValid = ElementTools.generateMethodBody(
|
||||
resultValid,
|
||||
"this.resultType = \"valid\";",
|
||||
"return this;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, resultValid);
|
||||
|
||||
Method mSetRows = ElementTools.generateSetterMethod(rowsField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mSetRows);
|
||||
// isResultValid
|
||||
Method isResultValid = ElementTools.generateMethod(
|
||||
"isResultValid",
|
||||
JavaVisibility.PUBLIC,
|
||||
booleanType
|
||||
);
|
||||
isResultValid = ElementTools.generateMethodBody(
|
||||
isResultValid,
|
||||
"return !this.isResultAny() && !this.isResultTrash();"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, isResultValid);
|
||||
|
||||
Method mGetRows = ElementTools.generateGetterMethod(rowsField);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, mGetRows);
|
||||
// resultTrash
|
||||
Method resultTrash = ElementTools.generateMethod(
|
||||
"resultTrash",
|
||||
JavaVisibility.PUBLIC,
|
||||
topLevelClass.getType()
|
||||
);
|
||||
resultTrash = ElementTools.generateMethodBody(
|
||||
resultTrash,
|
||||
"this.resultType = \"trash\";",
|
||||
"return this;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, resultTrash);
|
||||
|
||||
// isResultTrash
|
||||
Method isResultTrash = ElementTools.generateMethod(
|
||||
"isResultTrash",
|
||||
JavaVisibility.PUBLIC,
|
||||
booleanType
|
||||
);
|
||||
isResultTrash = ElementTools.generateMethodBody(
|
||||
isResultTrash,
|
||||
"return Objects.equals(this.resultType, \"trash\");"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, isResultTrash);
|
||||
|
||||
// resultAny
|
||||
Method resultAny = ElementTools.generateMethod(
|
||||
"resultAny",
|
||||
JavaVisibility.PUBLIC,
|
||||
topLevelClass.getType()
|
||||
);
|
||||
resultAny = ElementTools.generateMethodBody(
|
||||
resultAny,
|
||||
"this.resultType = \"any\";",
|
||||
"return this;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, resultAny);
|
||||
|
||||
// isResultAny
|
||||
Method isResultAny = ElementTools.generateMethod(
|
||||
"isResultAny",
|
||||
JavaVisibility.PUBLIC,
|
||||
booleanType
|
||||
);
|
||||
isResultAny = ElementTools.generateMethodBody(
|
||||
isResultAny,
|
||||
"return Objects.equals(this.resultType, \"any\");"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, isResultAny);
|
||||
}
|
||||
|
||||
// 提供几个快捷方法
|
||||
Method setLimit = ElementTools.generateMethod(
|
||||
Method setLimitByRows = ElementTools.generateMethod(
|
||||
"limit",
|
||||
JavaVisibility.PUBLIC,
|
||||
topLevelClass.getType(),
|
||||
new Parameter(integerWrapper, "rows")
|
||||
new Parameter(integerType, "rows")
|
||||
);
|
||||
setLimit = ElementTools.generateMethodBody(
|
||||
setLimit,
|
||||
setLimitByRows = ElementTools.generateMethodBody(
|
||||
setLimitByRows,
|
||||
"this.offset = null;",
|
||||
"this.rows = rows;",
|
||||
"return this;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, setLimit);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, setLimitByRows);
|
||||
|
||||
Method setLimit2 = ElementTools.generateMethod(
|
||||
// setLimitByOffsetRows
|
||||
Method setLimitByOffsetRows = ElementTools.generateMethod(
|
||||
"limit",
|
||||
JavaVisibility.PUBLIC,
|
||||
topLevelClass.getType(),
|
||||
new Parameter(integerWrapper, "offset"),
|
||||
new Parameter(integerWrapper, "rows")
|
||||
new Parameter(integerType, "offset"),
|
||||
new Parameter(integerType, "rows")
|
||||
);
|
||||
setLimit2 = ElementTools.generateMethodBody(
|
||||
setLimit2,
|
||||
setLimitByOffsetRows = ElementTools.generateMethodBody(
|
||||
setLimitByOffsetRows,
|
||||
"this.offset = offset;",
|
||||
"this.rows = rows;",
|
||||
"return this;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, setLimit2);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, setLimitByOffsetRows);
|
||||
|
||||
// limitOffset
|
||||
Method setLimitByOffsetOnly = ElementTools.generateMethod(
|
||||
"limitOffset",
|
||||
JavaVisibility.PUBLIC,
|
||||
topLevelClass.getType(),
|
||||
new Parameter(integerType, "offset"),
|
||||
new Parameter(integerType, "rows")
|
||||
);
|
||||
setLimitByOffsetOnly = ElementTools.generateMethodBody(
|
||||
setLimitByOffsetOnly,
|
||||
"this.offset = offset;",
|
||||
"this.rows = 999999999;",
|
||||
"return this;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, setLimitByOffsetOnly);
|
||||
|
||||
// usePage
|
||||
Method usePage = ElementTools.generateMethod(
|
||||
"usePage",
|
||||
JavaVisibility.PUBLIC,
|
||||
topLevelClass.getType(),
|
||||
new Parameter(integerWrapper, "pageNum"),
|
||||
new Parameter(integerWrapper, "pageSize")
|
||||
new Parameter(integerType, "pageNum"),
|
||||
new Parameter(integerType, "pageSize")
|
||||
);
|
||||
usePage = ElementTools.generateMethodBody(
|
||||
usePage,
|
||||
"pageSize = pageSize == null || pageSize <= 0 ? this.defaultPageSize : pageSize;",
|
||||
"pageNum = pageNum == null || pageNum < this.minPageNum ? this.minPageNum : pageNum;",
|
||||
"pageSize = pageSize == null || pageSize <= 0 ? 1 : pageSize;",
|
||||
"pageNum = pageNum == null || pageNum < this.startPageNum ? this.startPageNum : pageNum;",
|
||||
"if (pageSize >= this.ignorePageSize) {",
|
||||
"this.rows = null;",
|
||||
"this.offset = null;",
|
||||
"return this;",
|
||||
"}",
|
||||
"int cPageSize = pageSize > this.maxPageSize ? this.maxPageSize: pageSize;",
|
||||
"this.offset = (pageNum - this.minPageNum) * cPageSize;",
|
||||
"this.offset = (pageNum - this.startPageNum) * cPageSize;",
|
||||
"this.rows = cPageSize;",
|
||||
"return this;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, usePage);
|
||||
|
||||
// 计算获取当前页码
|
||||
// getPageNum 计算获取当前页码
|
||||
Method getPageNum = ElementTools.generateMethod(
|
||||
"getPageNum",
|
||||
JavaVisibility.PUBLIC,
|
||||
integerWrapper
|
||||
integerType
|
||||
);
|
||||
getPageNum = ElementTools.generateMethodBody(
|
||||
getPageNum,
|
||||
"if (this.rows == null || this.offset == null || this.rows == 0) {",
|
||||
"return this.minPageNum;",
|
||||
"return this.startPageNum;",
|
||||
"}",
|
||||
"return this.offset / this.rows + this.minPageNum;"
|
||||
"return this.offset / this.rows + this.startPageNum;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, getPageNum);
|
||||
// 计算获取当前每页数量
|
||||
|
||||
// getPageSize 计算获取当前每页数量
|
||||
Method getPageSize = ElementTools.generateMethod(
|
||||
"getPageSize",
|
||||
JavaVisibility.PUBLIC,
|
||||
integerWrapper
|
||||
integerType
|
||||
);
|
||||
getPageSize = ElementTools.generateMethodBody(
|
||||
getPageSize,
|
||||
@@ -247,14 +396,139 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, getPageSize);
|
||||
|
||||
// getRows
|
||||
Method getRows = ElementTools.generateMethod(
|
||||
"getRows",
|
||||
JavaVisibility.PUBLIC,
|
||||
integerType
|
||||
);
|
||||
getRows = ElementTools.generateMethodBody(
|
||||
getRows,
|
||||
"return this.rows;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, getRows);
|
||||
|
||||
// getOffset
|
||||
Method getOffset = ElementTools.generateMethod(
|
||||
"getOffset",
|
||||
JavaVisibility.PUBLIC,
|
||||
integerType
|
||||
);
|
||||
getOffset = ElementTools.generateMethodBody(
|
||||
getOffset,
|
||||
"return this.offset;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, getOffset);
|
||||
|
||||
// getLimitString
|
||||
Method getLimitString = ElementTools.generateMethod(
|
||||
"getLimitString",
|
||||
JavaVisibility.PUBLIC,
|
||||
stringType
|
||||
);
|
||||
getLimitString = ElementTools.generateMethodBody(
|
||||
getLimitString,
|
||||
"if (getRows() != null) {",
|
||||
"if (getOffset() != null) {",
|
||||
"return getOffset() + \",\" + getRows();",
|
||||
"} else {",
|
||||
"return getRows() + \"\";",
|
||||
"}",
|
||||
"}",
|
||||
"return null;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, getLimitString);
|
||||
|
||||
// getWhereString
|
||||
Method getWhereString = ElementTools.generateMethod(
|
||||
"getWhereString",
|
||||
JavaVisibility.PUBLIC,
|
||||
stringType
|
||||
);
|
||||
getWhereString = ElementTools.generateMethodBody(
|
||||
getWhereString,
|
||||
"if (getOredCriteria() != null) {",
|
||||
"List<String> whereGroup = new ArrayList<>();",
|
||||
"for (Criteria criteria : getOredCriteria()) {",
|
||||
"List<String> criterionList = new ArrayList<>();",
|
||||
"for (Criterion criterion : criteria.getAllCriteria()) {",
|
||||
"if (criterion.isNoValue()) {",
|
||||
"criterionList.add(criterion.getCondition());",
|
||||
"} else if (criterion.isBetweenValue()) {",
|
||||
"criterionList.add(criterion.getCondition() + \" \" + criterion.getValue() + \",\" + criterion.getSecondValue());",
|
||||
"} else {",
|
||||
"criterionList.add(criterion.getCondition() + \" \" + criterion.getValue());",
|
||||
"}",
|
||||
"}",
|
||||
"whereGroup.add(String.join(\" and \", criterionList));",
|
||||
"}",
|
||||
"if (whereGroup.size() > 1) {",
|
||||
"List<String> mapWhereGroup = new ArrayList<>();",
|
||||
"for (String where : whereGroup) {",
|
||||
"mapWhereGroup.add(\"(\" + where + \")\");",
|
||||
"}",
|
||||
"whereGroup = mapWhereGroup;",
|
||||
"}",
|
||||
"return String.join(\" or \", whereGroup);",
|
||||
"}",
|
||||
"return null;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, getWhereString);
|
||||
|
||||
// cloneExample
|
||||
Method cloneExample = ElementTools.generateMethod(
|
||||
"cloneExample",
|
||||
JavaVisibility.PUBLIC,
|
||||
topLevelClass.getType()
|
||||
);
|
||||
cloneExample = ElementTools.generateMethodBody(
|
||||
cloneExample,
|
||||
exampleClassName + " newExample = new " + exampleClassName + "();",
|
||||
"newExample.rows = this.rows;",
|
||||
"newExample.offset = this.offset;",
|
||||
"newExample.maxPageSize = this.maxPageSize;",
|
||||
"newExample.ignorePageSize = this.ignorePageSize;",
|
||||
"newExample.startPageNum = this.startPageNum;",
|
||||
!ElementTools.isViewTable(introspectedTable) ? "newExample.resultType = this.resultType;" : "",
|
||||
hasBLOBColumns ? "newExample.withBLOBs = withBLOBs;" : "",
|
||||
"if (this.getOredCriteria() != null && !this.getOredCriteria().isEmpty()) {",
|
||||
"for (" + exampleClassName + ".Criteria oldCriteria : this.getOredCriteria()) {",
|
||||
exampleClassName + ".Criteria newCriteria = newExample.or();",
|
||||
"newCriteria.getCriteria().addAll(oldCriteria.getCriteria());",
|
||||
"}",
|
||||
"}",
|
||||
"newExample.setOrderByClause(this.getOrderByClause());",
|
||||
"return newExample;"
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, cloneExample);
|
||||
|
||||
// !!! clear 方法增加 offset 和 rows的清理
|
||||
boolean hasClear = false;
|
||||
List<Method> methodList = topLevelClass.getMethods();
|
||||
for (Method method : methodList) {
|
||||
if (method.getName().equals("clear")) {
|
||||
method.addBodyLine("rows = null;");
|
||||
method.addBodyLine("offset = null;");
|
||||
if (!ElementTools.isViewTable(introspectedTable)) {
|
||||
method.addBodyLine("resultType = null;");
|
||||
}
|
||||
hasClear = true;
|
||||
}
|
||||
}
|
||||
if (!hasClear) {
|
||||
Method clear = ElementTools.generateMethod(
|
||||
"clear",
|
||||
JavaVisibility.PUBLIC,
|
||||
new FullyQualifiedJavaType("void")
|
||||
);
|
||||
clear = ElementTools.generateMethodBody(
|
||||
clear,
|
||||
"rows = null;",
|
||||
"offset = null;",
|
||||
!ElementTools.isViewTable(introspectedTable) ? "resultType = null;" : ""
|
||||
);
|
||||
FormatTools.addMethodWithBestPosition(topLevelClass, clear);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -292,16 +566,77 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
|
||||
element.addElement(ifLimitNotNullElement);
|
||||
}
|
||||
|
||||
// ============================================ batchInsert ==========================================
|
||||
|
||||
private void addBatchInsertClientMethod(Interface interfaceObj, IntrospectedTable introspectedTable) {
|
||||
if (introspectedTable.getAllColumns().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
FullyQualifiedJavaType rowType = ElementTools.hasBLOBColumns(introspectedTable)
|
||||
? ElementTools.getModelTypeWithBLOBs(introspectedTable)
|
||||
: ElementTools.getModelTypeWithoutBLOBs(introspectedTable);
|
||||
FullyQualifiedJavaType listType = FullyQualifiedJavaType.getNewListInstance();
|
||||
listType.addTypeArgument(rowType);
|
||||
Parameter recordsParam = new Parameter(listType, "records");
|
||||
recordsParam.addAnnotation("@Param(\"records\")");
|
||||
|
||||
Method batchInsert = new Method("batchInsert");
|
||||
batchInsert.setAbstract(true);
|
||||
batchInsert.setVisibility(JavaVisibility.PUBLIC);
|
||||
batchInsert.setReturnType(FullyQualifiedJavaType.getIntInstance());
|
||||
batchInsert.addParameter(recordsParam);
|
||||
interfaceObj.addMethod(batchInsert);
|
||||
}
|
||||
|
||||
private void addBatchInsertXmlElement(Document document, IntrospectedTable introspectedTable) {
|
||||
if (introspectedTable.getAllColumns().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
String tableName = introspectedTable.getFullyQualifiedTableNameAtRuntime();
|
||||
StringBuilder columnList = new StringBuilder();
|
||||
StringBuilder foreachBody = new StringBuilder();
|
||||
foreachBody.append("(");
|
||||
boolean first = true;
|
||||
for (IntrospectedColumn column : introspectedTable.getAllColumns()) {
|
||||
if (!first) {
|
||||
columnList.append(", ");
|
||||
foreachBody.append(", ");
|
||||
}
|
||||
first = false;
|
||||
columnList.append(column.getActualColumnName());
|
||||
foreachBody.append("#{item.").append(column.getJavaProperty()).append("}");
|
||||
}
|
||||
foreachBody.append(")");
|
||||
|
||||
XmlElement foreach = new XmlElement("foreach");
|
||||
foreach.addAttribute(new Attribute("collection", "records"));
|
||||
foreach.addAttribute(new Attribute("item", "item"));
|
||||
foreach.addAttribute(new Attribute("separator", ","));
|
||||
foreach.addElement(new TextElement(foreachBody.toString()));
|
||||
|
||||
XmlElement insert = new XmlElement("insert");
|
||||
insert.addAttribute(new Attribute("id", "batchInsert"));
|
||||
insert.addElement(new TextElement(
|
||||
"insert into " + tableName + " (" + columnList + ") values"));
|
||||
insert.addElement(foreach);
|
||||
|
||||
document.getRootElement().addElement(insert);
|
||||
}
|
||||
|
||||
// ============================================ selectPrimaryKeyByExample ==========================================
|
||||
|
||||
@Override
|
||||
public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) {
|
||||
public boolean clientGenerated(Interface interfaceObj, IntrospectedTable introspectedTable) {
|
||||
if (introspectedTable.getTargetRuntime() != IntrospectedTable.TargetRuntime.MYBATIS3) {
|
||||
return true;
|
||||
return super.clientGenerated(interfaceObj, introspectedTable);
|
||||
}
|
||||
// 添加接口方法
|
||||
if (introspectedTable.getPrimaryKeyColumns().size() <= 0) {
|
||||
return true;
|
||||
interfaceObj.addImportedType(new FullyQualifiedJavaType("java.util.List"));
|
||||
interfaceObj.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Param"));
|
||||
|
||||
addBatchInsertClientMethod(interfaceObj, introspectedTable);
|
||||
|
||||
if (introspectedTable.getPrimaryKeyColumns().isEmpty()) {
|
||||
return super.clientGenerated(interfaceObj, introspectedTable);
|
||||
}
|
||||
// 获取主键列类型
|
||||
FullyQualifiedJavaType primaryType = introspectedTable.getPrimaryKeyColumns().get(0)
|
||||
@@ -317,19 +652,20 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(returnType);
|
||||
method.addParameter(new Parameter(exampleType, "example"));
|
||||
interfaze.addMethod(method);
|
||||
interfaceObj.addMethod(method);
|
||||
|
||||
return super.clientGenerated(interfaze, introspectedTable);
|
||||
return super.clientGenerated(interfaceObj, introspectedTable);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
|
||||
if (introspectedTable.getTargetRuntime() != IntrospectedTable.TargetRuntime.MYBATIS3) {
|
||||
return true;
|
||||
return super.sqlMapDocumentGenerated(document, introspectedTable);
|
||||
}
|
||||
addBatchInsertXmlElement(document, introspectedTable);
|
||||
if (introspectedTable.getPrimaryKeyColumns().size() <= 0) {
|
||||
return true;
|
||||
return super.sqlMapDocumentGenerated(document, introspectedTable);
|
||||
}
|
||||
// 获取主键列名
|
||||
String primaryKeyColumn = introspectedTable.getPrimaryKeyColumns().get(0)
|
||||
|
||||
@@ -1,955 +0,0 @@
|
||||
package com.iqudoo.framework.mybatis;
|
||||
|
||||
import com.iqudoo.framework.mybatis.utils.ElementTools;
|
||||
import org.mybatis.generator.api.*;
|
||||
import org.mybatis.generator.api.dom.DefaultJavaFormatter;
|
||||
import org.mybatis.generator.api.dom.java.*;
|
||||
import org.mybatis.generator.config.Context;
|
||||
import org.mybatis.generator.internal.util.StringUtility;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
@SuppressWarnings({"DuplicatedCode", "unused", "SpellCheckingInspection", "ExtractMethodRecommender"})
|
||||
public class TapeRepositoryGeneratorPlugin extends PluginAdapter {
|
||||
|
||||
// 固定配置项
|
||||
private String slowQueryLoggerTime = "300";
|
||||
private String snowflakeUtilClass = "com.iqudoo.framework.tape.modules.utils.SnowflakeUtil";
|
||||
private String snowflakeUtilGenId = "SnowflakeUtil.nextId()";
|
||||
private String facadeRepositoryPackage = "com.iqudoo.platform.application.facade.repository";
|
||||
private String domainRepositoryPackage = "com.iqudoo.platform.application.domain.repository";
|
||||
private String modelPackage = "com.iqudoo.platform.application.database.model";
|
||||
private String mapperPackage = "com.iqudoo.platform.application.database.mapper";
|
||||
private String targetProject = "src/main/java";
|
||||
private String viewKeyWords = "VIEW_,V_";
|
||||
|
||||
// 1.4.1版本专用:Java格式化器
|
||||
private JavaFormatter javaFormatter;
|
||||
|
||||
@Override
|
||||
public void setContext(Context context) {
|
||||
super.setContext(context);
|
||||
this.javaFormatter = new DefaultJavaFormatter();
|
||||
this.javaFormatter.setContext(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(List<String> warnings) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
super.setProperties(properties);
|
||||
// 读取自定义配置
|
||||
if (StringUtility.stringHasValue(properties.getProperty("slowQueryLoggerTime"))) {
|
||||
slowQueryLoggerTime = properties.getProperty("slowQueryLoggerTime");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("snowflakeUtilClass"))) {
|
||||
snowflakeUtilClass = properties.getProperty("snowflakeUtilClass");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("snowflakeUtilGenId"))) {
|
||||
snowflakeUtilGenId = properties.getProperty("snowflakeUtilGenId");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("facadeRepositoryPackage"))) {
|
||||
facadeRepositoryPackage = properties.getProperty("facadeRepositoryPackage");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("domainRepositoryPackage"))) {
|
||||
domainRepositoryPackage = properties.getProperty("domainRepositoryPackage");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("modelPackage"))) {
|
||||
modelPackage = properties.getProperty("modelPackage");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("mapperPackage"))) {
|
||||
mapperPackage = properties.getProperty("mapperPackage");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("targetProject"))) {
|
||||
targetProject = properties.getProperty("targetProject");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("viewKeyWords"))) {
|
||||
viewKeyWords = properties.getProperty("viewKeyWords").toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心方法:视图表过滤 + 生成完整Repository代码
|
||||
*/
|
||||
@Override
|
||||
public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
|
||||
List<GeneratedJavaFile> generatedJavaFiles = new ArrayList<>();
|
||||
|
||||
// 视图表过滤逻辑
|
||||
String tableName = introspectedTable.getFullyQualifiedTable().getIntrospectedTableName().toUpperCase();
|
||||
if (isViewTable(tableName)) {
|
||||
return generatedJavaFiles;
|
||||
}
|
||||
|
||||
// 非视图表,正常生成
|
||||
String domainObjectName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
|
||||
String exampleClassName = domainObjectName + "Example";
|
||||
String mapperClassName = domainObjectName + "Mapper";
|
||||
String repositoryInterfaceName = "I" + domainObjectName + "Repository";
|
||||
String repositoryImplName = domainObjectName + "RepositoryImpl";
|
||||
boolean hasBLOBColumns = ElementTools.hasBLOBColumns(introspectedTable);
|
||||
|
||||
// 生成Repository接口(核心修改:手动添加所有方法,不再继承父接口)
|
||||
Interface repositoryInterface = generateRepositoryInterface(repositoryInterfaceName, domainObjectName, exampleClassName);
|
||||
GeneratedJavaFile interfaceFile = new GeneratedJavaFile(
|
||||
repositoryInterface,
|
||||
targetProject,
|
||||
"UTF-8",
|
||||
javaFormatter
|
||||
);
|
||||
generatedJavaFiles.add(interfaceFile);
|
||||
|
||||
// 生成Repository实现类(逻辑不变)
|
||||
TopLevelClass repositoryImpl = generateRepositoryImpl(
|
||||
repositoryImplName,
|
||||
repositoryInterfaceName,
|
||||
domainObjectName,
|
||||
exampleClassName,
|
||||
mapperClassName,
|
||||
introspectedTable,
|
||||
hasBLOBColumns
|
||||
);
|
||||
GeneratedJavaFile implFile = new GeneratedJavaFile(
|
||||
repositoryImpl,
|
||||
targetProject,
|
||||
"UTF-8",
|
||||
javaFormatter
|
||||
);
|
||||
generatedJavaFiles.add(implFile);
|
||||
|
||||
// 手动写入磁盘
|
||||
generateJavaFileToDisk(repositoryInterface, facadeRepositoryPackage);
|
||||
generateJavaFileToDisk(repositoryImpl, domainRepositoryPackage);
|
||||
|
||||
return generatedJavaFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为视图表(支持多关键字匹配)
|
||||
*/
|
||||
private boolean isViewTable(String tableName) {
|
||||
if (StringUtility.stringHasValue(viewKeyWords)) {
|
||||
String[] keywords = viewKeyWords.split(",");
|
||||
for (String keyword : keywords) {
|
||||
if (tableName.contains(keyword.trim().toUpperCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心修改:生成Repository接口(手动添加所有方法,无继承,匹配指定格式)
|
||||
*/
|
||||
private Interface generateRepositoryInterface(String interfaceName, String modelClassName, String exampleClassName) {
|
||||
Interface repositoryInterface = new Interface(facadeRepositoryPackage + "." + interfaceName);
|
||||
repositoryInterface.setVisibility(JavaVisibility.PUBLIC);
|
||||
|
||||
// 添加必要的导入(仅保留model和example,移除ModelDataRepository)
|
||||
repositoryInterface.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + modelClassName));
|
||||
repositoryInterface.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + exampleClassName));
|
||||
repositoryInterface.addImportedType(new FullyQualifiedJavaType("java.util.List"));
|
||||
|
||||
// 1. trashById
|
||||
Method trashByIdMethod = new Method("trashById");
|
||||
trashByIdMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
trashByIdMethod.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
trashByIdMethod.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
trashByIdMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
trashByIdMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(trashByIdMethod);
|
||||
|
||||
// 2. trashAll
|
||||
Method trashAllMethod = new Method("trashAll");
|
||||
trashAllMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
trashAllMethod.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
trashAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
trashAllMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
trashAllMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(trashAllMethod);
|
||||
|
||||
// 3. deleteById
|
||||
Method deleteByIdMethod = new Method("deleteById");
|
||||
deleteByIdMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
deleteByIdMethod.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
deleteByIdMethod.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
deleteByIdMethod.addParameter(new Parameter(new FullyQualifiedJavaType("boolean"), "release"));
|
||||
deleteByIdMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
deleteByIdMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(deleteByIdMethod);
|
||||
|
||||
// 4. deleteAll
|
||||
Method deleteAllMethod = new Method("deleteAll");
|
||||
deleteAllMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
deleteAllMethod.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
deleteAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
deleteAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType("boolean"), "release"));
|
||||
deleteAllMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
deleteAllMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(deleteAllMethod);
|
||||
|
||||
// 5. recoverById
|
||||
Method recoverByIdMethod = new Method("recoverById");
|
||||
recoverByIdMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
recoverByIdMethod.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
recoverByIdMethod.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
recoverByIdMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
recoverByIdMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(recoverByIdMethod);
|
||||
|
||||
// 6. recoverAll
|
||||
Method recoverAllMethod = new Method("recoverAll");
|
||||
recoverAllMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
recoverAllMethod.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
recoverAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
recoverAllMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
recoverAllMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(recoverAllMethod);
|
||||
|
||||
// 7. findAnyById
|
||||
Method findAnyByIdMethod = new Method("findAnyById");
|
||||
findAnyByIdMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
findAnyByIdMethod.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
findAnyByIdMethod.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
findAnyByIdMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
findAnyByIdMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(findAnyByIdMethod);
|
||||
|
||||
// 8. findValidById
|
||||
Method findValidByIdMethod = new Method("findValidById");
|
||||
findValidByIdMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
findValidByIdMethod.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
findValidByIdMethod.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
findValidByIdMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
findValidByIdMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(findValidByIdMethod);
|
||||
|
||||
// 9. findTrashById
|
||||
Method findTrashByIdMethod = new Method("findTrashById");
|
||||
findTrashByIdMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
findTrashByIdMethod.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
findTrashByIdMethod.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
findTrashByIdMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
findTrashByIdMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(findTrashByIdMethod);
|
||||
|
||||
// 10. findValidOne
|
||||
Method findValidOneMethod = new Method("findValidOne");
|
||||
findValidOneMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
findValidOneMethod.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
findValidOneMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
findValidOneMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
findValidOneMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(findValidOneMethod);
|
||||
|
||||
// 11. findTrashOne
|
||||
Method findTrashOneMethod = new Method("findTrashOne");
|
||||
findTrashOneMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
findTrashOneMethod.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
findTrashOneMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
findTrashOneMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
findTrashOneMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(findTrashOneMethod);
|
||||
|
||||
// 12. getValidList
|
||||
Method getValidListMethod = new Method("getValidList");
|
||||
getValidListMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
getValidListMethod.setReturnType(new FullyQualifiedJavaType("List<" + modelClassName + ">"));
|
||||
getValidListMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
getValidListMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
getValidListMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(getValidListMethod);
|
||||
|
||||
// 13. getTrashList
|
||||
Method getTrashListMethod = new Method("getTrashList");
|
||||
getTrashListMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
getTrashListMethod.setReturnType(new FullyQualifiedJavaType("List<" + modelClassName + ">"));
|
||||
getTrashListMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
getTrashListMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
getTrashListMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(getTrashListMethod);
|
||||
|
||||
// 14. countByValid
|
||||
Method countByValidMethod = new Method("countByValid");
|
||||
countByValidMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
countByValidMethod.setReturnType(new FullyQualifiedJavaType("long"));
|
||||
countByValidMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
countByValidMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
countByValidMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(countByValidMethod);
|
||||
|
||||
// 15. countByTrash
|
||||
Method countByTrashMethod = new Method("countByTrash");
|
||||
countByTrashMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
countByTrashMethod.setReturnType(new FullyQualifiedJavaType("long"));
|
||||
countByTrashMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
countByTrashMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
countByTrashMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(countByTrashMethod);
|
||||
|
||||
// 16. insert
|
||||
Method insertMethod = new Method("insert");
|
||||
insertMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
insertMethod.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
insertMethod.addParameter(new Parameter(new FullyQualifiedJavaType(modelClassName), "record"));
|
||||
insertMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
insertMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(insertMethod);
|
||||
|
||||
// 17. update
|
||||
Method updateMethod = new Method("update");
|
||||
updateMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
updateMethod.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
updateMethod.addParameter(new Parameter(new FullyQualifiedJavaType(modelClassName), "record"));
|
||||
updateMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
updateMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(updateMethod);
|
||||
|
||||
// 17. updateByExampleSelective
|
||||
Method updateByExampleSelectiveMethod = new Method("updateByExampleSelective");
|
||||
updateByExampleSelectiveMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
updateByExampleSelectiveMethod.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
updateByExampleSelectiveMethod.addParameter(new Parameter(new FullyQualifiedJavaType(modelClassName), "record"));
|
||||
updateByExampleSelectiveMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
updateByExampleSelectiveMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
updateByExampleSelectiveMethod.setAbstract(true);
|
||||
repositoryInterface.addMethod(updateByExampleSelectiveMethod);
|
||||
|
||||
return repositoryInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成Repository实现类(逻辑无修改)
|
||||
*/
|
||||
private TopLevelClass generateRepositoryImpl(
|
||||
String implClassName,
|
||||
String interfaceName,
|
||||
String modelClassName,
|
||||
String exampleClassName,
|
||||
String mapperClassName,
|
||||
IntrospectedTable introspectedTable,
|
||||
boolean hasBLOBColumns) {
|
||||
|
||||
TopLevelClass implClass = new TopLevelClass(domainRepositoryPackage + "." + implClassName);
|
||||
implClass.setVisibility(JavaVisibility.PUBLIC);
|
||||
implClass.addAnnotation("@SuppressWarnings(\"DuplicatedCode\")");
|
||||
implClass.addAnnotation("@Repository");
|
||||
|
||||
addImportPackages(implClass, modelClassName, exampleClassName, mapperClassName, interfaceName);
|
||||
|
||||
FullyQualifiedJavaType superInterface = new FullyQualifiedJavaType(facadeRepositoryPackage + "." + interfaceName);
|
||||
implClass.addSuperInterface(superInterface);
|
||||
|
||||
// slow query logger
|
||||
Field loggerField = new Field("LOGGER", new FullyQualifiedJavaType("Logger"));
|
||||
loggerField.setVisibility(JavaVisibility.PRIVATE);
|
||||
loggerField.setStatic(true);
|
||||
loggerField.setFinal(true);
|
||||
loggerField.setInitializationString("LoggerFactory.getLogger(" + implClassName + ".class)");
|
||||
implClass.addField(loggerField);
|
||||
|
||||
String mapperFieldName = lowerFirst(mapperClassName);
|
||||
Field mapperField = new Field(mapperFieldName, new FullyQualifiedJavaType(mapperPackage + "." + mapperClassName));
|
||||
mapperField.setVisibility(JavaVisibility.PRIVATE);
|
||||
mapperField.addAnnotation("@Resource");
|
||||
implClass.addField(mapperField);
|
||||
|
||||
// 原有方法生成逻辑(无修改)
|
||||
generateFindAnyByIdMethod(implClass, modelClassName, mapperFieldName, exampleClassName);
|
||||
generateFindValidByIdMethod(implClass, modelClassName, mapperFieldName, exampleClassName);
|
||||
generateFindTrashByIdMethod(implClass, modelClassName, mapperFieldName, exampleClassName);
|
||||
generateInsertMethod(implClass, modelClassName, mapperFieldName, introspectedTable);
|
||||
generateUpdateMethod(implClass, modelClassName, exampleClassName, mapperFieldName, introspectedTable, hasBLOBColumns);
|
||||
generateUpdateByExampleSelectiveMethod(implClass, modelClassName, exampleClassName, mapperFieldName);
|
||||
generateDeleteByIdMethod(implClass, modelClassName, mapperFieldName);
|
||||
generateDeleteAllMethod(implClass, modelClassName, exampleClassName, mapperFieldName);
|
||||
generateTrashByIdMethod(implClass, modelClassName, mapperFieldName);
|
||||
generateTrashAllMethod(implClass, modelClassName, exampleClassName, mapperFieldName);
|
||||
generateRecoverByIdMethod(implClass, modelClassName, mapperFieldName);
|
||||
generateRecoverAllMethod(implClass, modelClassName, exampleClassName, mapperFieldName);
|
||||
generateFindValidOneMethod(implClass, modelClassName, exampleClassName);
|
||||
generateFindTrashOneMethod(implClass, modelClassName, exampleClassName);
|
||||
generateGetValidListMethod(implClass, modelClassName, exampleClassName, mapperFieldName, hasBLOBColumns);
|
||||
generateGetTrashListMethod(implClass, modelClassName, exampleClassName, mapperFieldName, hasBLOBColumns);
|
||||
generateCountByValidMethod(implClass, exampleClassName, mapperFieldName);
|
||||
generateCountByTrashMethod(implClass, exampleClassName, mapperFieldName);
|
||||
|
||||
return implClass;
|
||||
}
|
||||
|
||||
// ------------------------ 所有原有方法(无修改) ------------------------
|
||||
private void generateDeleteAllMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName) {
|
||||
Method method = new Method("deleteAll");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType("boolean"), "release"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
// 方法体
|
||||
method.addBodyLine("if (release) {");
|
||||
method.addBodyLine("return " + mapperFieldName + ".deleteByExample(example);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {");
|
||||
method.addBodyLine("criteria.andIsDeleteEqualTo(0).andIsHiddenEqualTo(1);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine(modelClassName + " " + lowerFirst(modelClassName) + " = new " + modelClassName + "();");
|
||||
method.addBodyLine(lowerFirst(modelClassName) + ".setIsDelete(1);");
|
||||
method.addBodyLine(lowerFirst(modelClassName) + ".setUpdateTime(new Date());");
|
||||
method.addBodyLine("return " + mapperFieldName + ".updateByExampleSelective(" + lowerFirst(modelClassName) + ", example);");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateTrashAllMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName) {
|
||||
Method method = new Method("trashAll");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
// 方法体
|
||||
method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {");
|
||||
method.addBodyLine("criteria.andIsDeleteEqualTo(0).andIsHiddenEqualTo(0);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine(modelClassName + " " + lowerFirst(modelClassName) + " = new " + modelClassName + "();");
|
||||
method.addBodyLine(lowerFirst(modelClassName) + ".setIsHidden(1);");
|
||||
method.addBodyLine(lowerFirst(modelClassName) + ".setDeleteToken(" + lowerFirst(modelClassName) + ".getGuid() + \"\");");
|
||||
method.addBodyLine(lowerFirst(modelClassName) + ".setUpdateTime(new Date());");
|
||||
method.addBodyLine("return " + mapperFieldName + ".updateByExampleSelective(" + lowerFirst(modelClassName) + ", example);");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateRecoverAllMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName) {
|
||||
Method method = new Method("recoverAll");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
// 方法体
|
||||
method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {");
|
||||
method.addBodyLine("criteria.andIsDeleteEqualTo(0).andIsHiddenEqualTo(1);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine(modelClassName + " " + lowerFirst(modelClassName) + " = new " + modelClassName + "();");
|
||||
method.addBodyLine(lowerFirst(modelClassName) + ".setIsHidden(0);");
|
||||
method.addBodyLine(lowerFirst(modelClassName) + ".setDeleteToken(\"VALID\");");
|
||||
method.addBodyLine(lowerFirst(modelClassName) + ".setUpdateTime(new Date());");
|
||||
method.addBodyLine("return " + mapperFieldName + ".updateByExampleSelective(" + lowerFirst(modelClassName) + ", example);");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateJavaFileToDisk(Interface anInterface, String packageName) {
|
||||
try {
|
||||
String packagePath = packageName.replace('.', File.separatorChar);
|
||||
File targetDir = new File(targetProject, packagePath);
|
||||
if (!targetDir.exists()) {
|
||||
boolean mkdirs = targetDir.mkdirs();
|
||||
if (!mkdirs) {
|
||||
throw new RuntimeException("Created dir: " + targetDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
String className = anInterface.getType().getShortName();
|
||||
File javaFile = new File(targetDir, className + ".java");
|
||||
String content = javaFormatter.getFormattedContent(anInterface);
|
||||
java.nio.file.Files.write(javaFile.toPath(), content.getBytes(StandardCharsets.UTF_8));
|
||||
System.out.println("Created: " + javaFile.getAbsolutePath());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Create failure: " + anInterface.getType().getShortName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateJavaFileToDisk(TopLevelClass clazz, String packageName) {
|
||||
try {
|
||||
String packagePath = packageName.replace('.', File.separatorChar);
|
||||
File targetDir = new File(targetProject, packagePath);
|
||||
if (!targetDir.exists()) {
|
||||
boolean mkdirs = targetDir.mkdirs();
|
||||
if (!mkdirs) {
|
||||
throw new RuntimeException("Created dir: " + targetDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
String className = clazz.getType().getShortName();
|
||||
File javaFile = new File(targetDir, className + ".java");
|
||||
String content = javaFormatter.getFormattedContent(clazz);
|
||||
java.nio.file.Files.write(javaFile.toPath(), content.getBytes(StandardCharsets.UTF_8));
|
||||
System.out.println("Created: " + javaFile.getAbsolutePath());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Create failure: " + clazz.getType().getShortName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addImportPackages(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperClassName, String interfaceName) {
|
||||
implClass.addImportedType(new FullyQualifiedJavaType(snowflakeUtilClass));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType(mapperPackage + "." + mapperClassName));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + modelClassName));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + exampleClassName));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType(facadeRepositoryPackage + "." + interfaceName));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("org.springframework.stereotype.Repository"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("javax.annotation.Resource"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("org.slf4j.Logger"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("org.slf4j.LoggerFactory"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("java.util.ArrayList"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("java.util.Date"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("java.util.List"));
|
||||
}
|
||||
|
||||
private void generateFindAnyByIdMethod(TopLevelClass implClass, String modelClassName, String mapperFieldName, String exampleClassName) {
|
||||
Method method = new Method("findAnyById");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine(modelClassName + " aDo = " + mapperFieldName + ".selectByPrimaryKey(id);");
|
||||
method.addBodyLine("if (aDo != null && aDo.getIsDelete() == 1) {");
|
||||
method.addBodyLine("return null;");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return aDo;");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateFindValidByIdMethod(TopLevelClass implClass, String modelClassName, String mapperFieldName, String exampleClassName) {
|
||||
Method method = new Method("findValidById");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine(modelClassName + " aDo = " + mapperFieldName + ".selectByPrimaryKey(id);");
|
||||
method.addBodyLine("if (aDo != null && (aDo.getIsDelete() == 1 || aDo.getIsHidden() == 1)) {");
|
||||
method.addBodyLine("return null;");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return aDo;");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateFindTrashByIdMethod(TopLevelClass implClass, String modelClassName, String mapperFieldName, String exampleClassName) {
|
||||
Method method = new Method("findTrashById");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine(modelClassName + " aDo = " + mapperFieldName + ".selectByPrimaryKey(id);");
|
||||
method.addBodyLine("if (aDo != null && (aDo.getIsDelete() == 1 || aDo.getIsHidden() == 0)) {");
|
||||
method.addBodyLine("return null;");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return aDo;");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateInsertMethod(TopLevelClass implClass, String modelClassName, String mapperFieldName, IntrospectedTable introspectedTable) {
|
||||
Method method = new Method("insert");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(modelClassName), "record"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine(modelClassName + " aDo = new " + modelClassName + "();");
|
||||
method.addBodyLine("if (record.getGuid() != null) {");
|
||||
method.addBodyLine("aDo.setGuid(record.getGuid());");
|
||||
method.addBodyLine("} else {");
|
||||
method.addBodyLine("Long guid = " + snowflakeUtilGenId + ";");
|
||||
method.addBodyLine("aDo.setGuid(guid);");
|
||||
method.addBodyLine("}");
|
||||
|
||||
for (IntrospectedColumn column : introspectedTable.getAllColumns()) {
|
||||
String fieldName = column.getJavaProperty();
|
||||
String setterMethod = "set" + upperFirst(fieldName);
|
||||
String getterMethod = "get" + upperFirst(fieldName);
|
||||
|
||||
if ("guid".equals(fieldName) || "isDelete".equals(fieldName) || "isHidden".equals(fieldName)
|
||||
|| "deleteToken".equals(fieldName) || "dataVersion".equals(fieldName)
|
||||
|| "createTime".equals(fieldName) || "updateTime".equals(fieldName)) {
|
||||
continue;
|
||||
}
|
||||
method.addBodyLine("aDo." + setterMethod + "(record." + getterMethod + "());");
|
||||
}
|
||||
|
||||
method.addBodyLine("aDo.setIsDelete(0);");
|
||||
method.addBodyLine("aDo.setIsHidden(0);");
|
||||
method.addBodyLine("aDo.setDeleteToken(\"VALID\");");
|
||||
method.addBodyLine("aDo.setDataVersion(1);");
|
||||
method.addBodyLine("aDo.setCreateTime(new Date());");
|
||||
method.addBodyLine("aDo.setUpdateTime(new Date());");
|
||||
|
||||
method.addBodyLine("int count = " + mapperFieldName + ".insert(aDo);");
|
||||
method.addBodyLine("if (count > 0) {");
|
||||
method.addBodyLine("return aDo;");
|
||||
method.addBodyLine("}");
|
||||
|
||||
method.addBodyLine("// optimistic locking with data version and guid");
|
||||
method.addBodyLine("record.setGuid(aDo.getGuid());");
|
||||
method.addBodyLine("record.setDataVersion(aDo.getDataVersion());");
|
||||
method.addBodyLine("record.setCreateTime(aDo.getCreateTime());");
|
||||
method.addBodyLine("record.setUpdateTime(aDo.getUpdateTime());");
|
||||
method.addBodyLine("throw new Throwable(\"Database insert failed, " + modelClassName + ": \" + aDo);");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateUpdateMethod(TopLevelClass implClass, String modelClassName, String exampleClassName,
|
||||
String mapperFieldName, IntrospectedTable introspectedTable, boolean hasBLOBColumns) {
|
||||
Method method = new Method("update");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(modelClassName), "record"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine(modelClassName + " aDo = findValidById(record.getGuid());");
|
||||
method.addBodyLine("if (aDo == null) {");
|
||||
method.addBodyLine("throw new Throwable(\"Database record not found, " + modelClassName + " GUID:\" + record.getGuid());");
|
||||
method.addBodyLine("}");
|
||||
|
||||
for (IntrospectedColumn column : introspectedTable.getAllColumns()) {
|
||||
String fieldName = column.getJavaProperty();
|
||||
String setterMethod = "set" + upperFirst(fieldName);
|
||||
String getterMethod = "get" + upperFirst(fieldName);
|
||||
|
||||
if ("guid".equals(fieldName) || "isDelete".equals(fieldName) || "isHidden".equals(fieldName)
|
||||
|| "deleteToken".equals(fieldName) || "dataVersion".equals(fieldName)
|
||||
|| "createTime".equals(fieldName) || "updateTime".equals(fieldName)) {
|
||||
continue;
|
||||
}
|
||||
method.addBodyLine("if (record." + getterMethod + "() != null) {");
|
||||
method.addBodyLine("aDo." + setterMethod + "(record." + getterMethod + "());");
|
||||
method.addBodyLine("}");
|
||||
}
|
||||
|
||||
method.addBodyLine(exampleClassName + " updateWhere = new " + exampleClassName + "();");
|
||||
method.addBodyLine("Integer lockDataVersion = record.getDataVersion();");
|
||||
method.addBodyLine("if (lockDataVersion == null) {");
|
||||
method.addBodyLine("lockDataVersion = aDo.getDataVersion();");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("updateWhere.createCriteria()");
|
||||
method.addBodyLine(" .andGuidEqualTo(aDo.getGuid())");
|
||||
method.addBodyLine(" .andDataVersionEqualTo(lockDataVersion);");
|
||||
method.addBodyLine("aDo.setDataVersion(aDo.getDataVersion() + 1);");
|
||||
method.addBodyLine("aDo.setUpdateTime(new Date());");
|
||||
method.addBodyLine("// update data version");
|
||||
method.addBodyLine("record.setDataVersion(aDo.getDataVersion());");
|
||||
method.addBodyLine("record.setUpdateTime(aDo.getUpdateTime());");
|
||||
|
||||
String updateMethod = hasBLOBColumns ? "updateByExampleWithBLOBs" : "updateByExample";
|
||||
method.addBodyLine("return " + mapperFieldName + "." + updateMethod + "(aDo, updateWhere);");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateUpdateByExampleSelectiveMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName) {
|
||||
Method method = new Method("updateByExampleSelective");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(modelClassName), "record"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
// 方法体
|
||||
method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {");
|
||||
method.addBodyLine("criteria.andIsDeleteEqualTo(0).andIsHiddenEqualTo(0);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("record.setUpdateTime(new Date());");
|
||||
method.addBodyLine("// It is not supported to directly modify the following columns");
|
||||
method.addBodyLine("record.setIsHidden(null);");
|
||||
method.addBodyLine("record.setIsDelete(null);");
|
||||
method.addBodyLine("record.setDeleteToken(null);");
|
||||
method.addBodyLine("record.setDataVersion(null);");
|
||||
method.addBodyLine("record.setCreateTime(null);");
|
||||
method.addBodyLine("return " + mapperFieldName + ".updateByExampleSelective(record, example);");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateDeleteByIdMethod(TopLevelClass implClass, String modelClassName, String mapperFieldName) {
|
||||
Method method = new Method("deleteById");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType("boolean"), "release"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine(modelClassName + " aDo = findValidById(id);");
|
||||
method.addBodyLine("if (aDo == null) {");
|
||||
method.addBodyLine("return 0;");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("if (release) {");
|
||||
method.addBodyLine("return " + mapperFieldName + ".deleteByPrimaryKey(aDo.getGuid());");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("aDo.setIsDelete(1);");
|
||||
method.addBodyLine("aDo.setUpdateTime(new Date());");
|
||||
method.addBodyLine("return " + mapperFieldName + ".updateByPrimaryKey(aDo);");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateTrashByIdMethod(TopLevelClass implClass, String modelClassName, String mapperFieldName) {
|
||||
Method method = new Method("trashById");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine(modelClassName + " aDo = findValidById(id);");
|
||||
method.addBodyLine("if (aDo == null) {");
|
||||
method.addBodyLine("return 0;");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("aDo.setIsHidden(1);");
|
||||
method.addBodyLine("aDo.setDeleteToken(aDo.getGuid() + \"\");");
|
||||
method.addBodyLine("aDo.setUpdateTime(new Date());");
|
||||
method.addBodyLine("return " + mapperFieldName + ".updateByPrimaryKey(aDo);");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateRecoverByIdMethod(TopLevelClass implClass, String modelClassName, String mapperFieldName) {
|
||||
Method method = new Method("recoverById");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("int"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType("long"), "id"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine(modelClassName + " aDo = findTrashById(id);");
|
||||
method.addBodyLine("if (aDo == null) {");
|
||||
method.addBodyLine("return 0;");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("if (aDo.getIsDelete() == 1) {");
|
||||
method.addBodyLine("return 0;");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("aDo.setIsHidden(0);");
|
||||
method.addBodyLine("aDo.setDeleteToken(\"VALID\");");
|
||||
method.addBodyLine("aDo.setUpdateTime(new Date());");
|
||||
method.addBodyLine("return " + mapperFieldName + ".updateByPrimaryKey(aDo);");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateFindValidOneMethod(TopLevelClass implClass, String modelClassName, String exampleClassName) {
|
||||
Method method = new Method("findValidOne");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine("example.usePage(1, 1);");
|
||||
method.addBodyLine("List<" + modelClassName + "> dataList = getValidList(example);");
|
||||
method.addBodyLine("if (dataList != null && !dataList.isEmpty()) {");
|
||||
method.addBodyLine("return dataList.get(0);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return null;");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateFindTrashOneMethod(TopLevelClass implClass, String modelClassName, String exampleClassName) {
|
||||
Method method = new Method("findTrashOne");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType(modelClassName));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine("example.usePage(1, 1);");
|
||||
method.addBodyLine("List<" + modelClassName + "> dataList = getTrashList(example);");
|
||||
method.addBodyLine("if (dataList != null && !dataList.isEmpty()) {");
|
||||
method.addBodyLine("return dataList.get(0);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return null;");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateGetValidListMethod(TopLevelClass implClass, String modelClassName, String exampleClassName,
|
||||
String mapperFieldName, boolean hasBLOBColumns) {
|
||||
Method method = new Method("getValidList");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("List<" + modelClassName + ">"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {");
|
||||
method.addBodyLine("criteria.andIsDeleteEqualTo(0).andIsHiddenEqualTo(0);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("long startTime = new Date().getTime();");
|
||||
method.addBodyLine("try {");
|
||||
method.addBodyLine("if (example.getRows() != null && example.getOffset() != null) {");
|
||||
method.addBodyLine("List<Long> primaryKeyList = " + mapperFieldName + ".selectPrimaryKeyByExample(example);");
|
||||
method.addBodyLine("if (primaryKeyList == null || primaryKeyList.isEmpty()) {");
|
||||
method.addBodyLine("return new ArrayList<>();");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("long findPrimaryKeyTime = new Date().getTime() - startTime;");
|
||||
method.addBodyLine("if (findPrimaryKeyTime > " + slowQueryLoggerTime + ") {");
|
||||
method.addBodyLine("LOGGER.error(\"find valid list primary key use long time: \" + findPrimaryKeyTime + \"ms\");");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("String oldOrderByClause = example.getOrderByClause();");
|
||||
if (hasBLOBColumns) {
|
||||
method.addBodyLine("Boolean withBLOBsFlag = example.isWithBLOBs();");
|
||||
}
|
||||
method.addBodyLine("example = new " + exampleClassName + "();");
|
||||
method.addBodyLine("example.createCriteria().andGuidIn(primaryKeyList);");
|
||||
method.addBodyLine("example.setOrderByClause(oldOrderByClause);");
|
||||
if (hasBLOBColumns) {
|
||||
method.addBodyLine("example.setWithBLOBs(withBLOBsFlag);");
|
||||
}
|
||||
method.addBodyLine("}");
|
||||
|
||||
if (hasBLOBColumns) {
|
||||
method.addBodyLine("if (example.isWithBLOBs()) {");
|
||||
method.addBodyLine("return " + mapperFieldName + ".selectByExampleWithBLOBs(example);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return " + mapperFieldName + ".selectByExample(example);");
|
||||
} else {
|
||||
method.addBodyLine("return " + mapperFieldName + ".selectByExample(example);");
|
||||
}
|
||||
method.addBodyLine("} finally {");
|
||||
method.addBodyLine("long useTime = new Date().getTime() - startTime;");
|
||||
method.addBodyLine("if (useTime > " + slowQueryLoggerTime + ") {");
|
||||
method.addBodyLine("LOGGER.error(\"get valid list use long time: \" + useTime + \"ms\");");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("}");
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateGetTrashListMethod(TopLevelClass implClass, String modelClassName, String exampleClassName,
|
||||
String mapperFieldName, boolean hasBLOBColumns) {
|
||||
Method method = new Method("getTrashList");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("List<" + modelClassName + ">"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {");
|
||||
method.addBodyLine("criteria.andIsDeleteEqualTo(0).andIsHiddenEqualTo(1);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("long startTime = new Date().getTime();");
|
||||
method.addBodyLine("try {");
|
||||
method.addBodyLine("if (example.getRows() != null && example.getOffset() != null) {");
|
||||
method.addBodyLine("List<Long> primaryKeyList = " + mapperFieldName + ".selectPrimaryKeyByExample(example);");
|
||||
method.addBodyLine("if (primaryKeyList == null || primaryKeyList.isEmpty()) {");
|
||||
method.addBodyLine("return new ArrayList<>();");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("long findPrimaryKeyTime = new Date().getTime() - startTime;");
|
||||
method.addBodyLine("if (findPrimaryKeyTime > " + slowQueryLoggerTime + ") {");
|
||||
method.addBodyLine("LOGGER.error(\"find trash list primary key use long time: \" + findPrimaryKeyTime + \"ms\");");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("String oldOrderByClause = example.getOrderByClause();");
|
||||
if (hasBLOBColumns) {
|
||||
method.addBodyLine("Boolean withBLOBsFlag = example.isWithBLOBs();");
|
||||
}
|
||||
method.addBodyLine("example = new " + exampleClassName + "();");
|
||||
method.addBodyLine("example.createCriteria().andGuidIn(primaryKeyList);");
|
||||
method.addBodyLine("example.setOrderByClause(oldOrderByClause);");
|
||||
if (hasBLOBColumns) {
|
||||
method.addBodyLine("example.setWithBLOBs(withBLOBsFlag);");
|
||||
}
|
||||
method.addBodyLine("}");
|
||||
|
||||
if (hasBLOBColumns) {
|
||||
method.addBodyLine("if (example.isWithBLOBs()) {");
|
||||
method.addBodyLine("return " + mapperFieldName + ".selectByExampleWithBLOBs(example);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return " + mapperFieldName + ".selectByExample(example);");
|
||||
} else {
|
||||
method.addBodyLine("return " + mapperFieldName + ".selectByExample(example);");
|
||||
}
|
||||
method.addBodyLine("} finally {");
|
||||
method.addBodyLine("long useTime = new Date().getTime() - startTime;");
|
||||
method.addBodyLine("if (useTime > " + slowQueryLoggerTime + ") {");
|
||||
method.addBodyLine("LOGGER.error(\"get trash list use long time: \" + useTime + \"ms\");");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("}");
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateCountByValidMethod(TopLevelClass implClass, String exampleClassName, String mapperFieldName) {
|
||||
Method method = new Method("countByValid");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("long"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {");
|
||||
method.addBodyLine("criteria.andIsDeleteEqualTo(0).andIsHiddenEqualTo(0);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("long startTime = new Date().getTime();");
|
||||
method.addBodyLine("try {");
|
||||
method.addBodyLine("return " + mapperFieldName + ".countByExample(example);");
|
||||
method.addBodyLine("} finally {");
|
||||
method.addBodyLine("long useTime = new Date().getTime() - startTime;");
|
||||
method.addBodyLine("if (useTime > " + slowQueryLoggerTime + ") {");
|
||||
method.addBodyLine("LOGGER.error(\"count by valid use long time: \" + useTime + \"ms\");");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("}");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private void generateCountByTrashMethod(TopLevelClass implClass, String exampleClassName, String mapperFieldName) {
|
||||
Method method = new Method("countByTrash");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("long"));
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {");
|
||||
method.addBodyLine("criteria.andIsDeleteEqualTo(0).andIsHiddenEqualTo(1);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("long startTime = new Date().getTime();");
|
||||
method.addBodyLine("try {");
|
||||
method.addBodyLine("return " + mapperFieldName + ".countByExample(example);");
|
||||
method.addBodyLine("} finally {");
|
||||
method.addBodyLine("long useTime = new Date().getTime() - startTime;");
|
||||
method.addBodyLine("if (useTime > " + slowQueryLoggerTime + ") {");
|
||||
method.addBodyLine("LOGGER.error(\"count by trash use long time: \" + useTime + \"ms\");");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("}");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
private String upperFirst(String str) {
|
||||
if (str == null || str.isEmpty()) {
|
||||
return str;
|
||||
}
|
||||
return str.substring(0, 1).toUpperCase() + str.substring(1);
|
||||
}
|
||||
|
||||
private String lowerFirst(String str) {
|
||||
if (str == null || str.isEmpty()) {
|
||||
return str;
|
||||
}
|
||||
return str.substring(0, 1).toLowerCase() + str.substring(1);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
package com.iqudoo.framework.mybatis;
|
||||
|
||||
import com.iqudoo.framework.mybatis.utils.ElementTools;
|
||||
import com.iqudoo.framework.mybatis.utils.UtilTools;
|
||||
import org.mybatis.generator.api.GeneratedJavaFile;
|
||||
import org.mybatis.generator.api.IntrospectedTable;
|
||||
import org.mybatis.generator.api.JavaFormatter;
|
||||
@@ -8,68 +9,91 @@ import org.mybatis.generator.api.PluginAdapter;
|
||||
import org.mybatis.generator.api.dom.DefaultJavaFormatter;
|
||||
import org.mybatis.generator.api.dom.java.*;
|
||||
import org.mybatis.generator.config.Context;
|
||||
import org.mybatis.generator.config.TableConfiguration;
|
||||
import org.mybatis.generator.internal.util.StringUtility;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
@SuppressWarnings({"DuplicatedCode", "SpellCheckingInspection", "ExtractMethodRecommender"})
|
||||
public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
public class TapeViewRepositoryGeneratorPlugin extends PluginAdapter {
|
||||
|
||||
// 视图Repo包配置(可通过配置文件自定义)
|
||||
private String slowQueryLoggerTime = "300";
|
||||
private String facadeRepoviewPackage = "com.iqudoo.platform.application.facade.repoview";
|
||||
private String domainRepoviewPackage = "com.iqudoo.platform.application.domain.repoview";
|
||||
private String slowQueryLoggerLevel = "error";
|
||||
private String modelPackage = "com.iqudoo.platform.application.database.model";
|
||||
private String mapperPackage = "com.iqudoo.platform.application.database.mapper";
|
||||
private String facadeViewRepositoryPackage = "com.iqudoo.platform.application.facade.repoview";
|
||||
private String domainViewRepositoryPackage = "com.iqudoo.platform.application.domain.repoview";
|
||||
private String domainViewRepositoryType = "Repository";
|
||||
private String targetProject = "src/main/java";
|
||||
|
||||
// 视图名称关键字(可配置)
|
||||
private String viewKeyWords = "VIEW_,V_";
|
||||
|
||||
// 1.4.1版本专用格式化器
|
||||
private JavaFormatter javaFormatter;
|
||||
|
||||
@Override
|
||||
public void setContext(Context context) {
|
||||
super.setContext(context);
|
||||
this.javaFormatter = new DefaultJavaFormatter();
|
||||
this.javaFormatter.setContext(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(List<String> warnings) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
super.setProperties(properties);
|
||||
// 读取自定义配置
|
||||
if (StringUtility.stringHasValue(properties.getProperty("slowQueryLoggerTime"))) {
|
||||
slowQueryLoggerTime = properties.getProperty("slowQueryLoggerTime");
|
||||
public void setContext(Context context) {
|
||||
super.setContext(context);
|
||||
this.javaFormatter = new DefaultJavaFormatter();
|
||||
this.javaFormatter.setContext(context);
|
||||
resolveConfiguration();
|
||||
}
|
||||
|
||||
private void resolveConfiguration() {
|
||||
targetProject = stringConfig("targetProject", targetProject);
|
||||
slowQueryLoggerTime = stringConfig("slowQueryLoggerTime", slowQueryLoggerTime);
|
||||
slowQueryLoggerLevel = stringConfig("slowQueryLoggerLevel", slowQueryLoggerLevel);
|
||||
facadeViewRepositoryPackage = stringConfig("facadeViewRepositoryPackage", facadeViewRepositoryPackage);
|
||||
domainViewRepositoryPackage = stringConfig("domainViewRepositoryPackage", domainViewRepositoryPackage);
|
||||
domainViewRepositoryType = stringConfig("domainViewRepositoryType", domainViewRepositoryType);
|
||||
mapperPackage = stringConfig("mapperPackage", mapperPackage);
|
||||
modelPackage = stringConfig("modelPackage", modelPackage);
|
||||
}
|
||||
|
||||
private String stringConfig(String key, String defaultValue) {
|
||||
String v = properties.getProperty(key);
|
||||
if (StringUtility.stringHasValue(v)) {
|
||||
return v;
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("facadeRepoviewPackage"))) {
|
||||
facadeRepoviewPackage = properties.getProperty("facadeRepoviewPackage");
|
||||
if (context != null) {
|
||||
v = context.getProperty(key);
|
||||
if (StringUtility.stringHasValue(v)) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("domainRepoviewPackage"))) {
|
||||
domainRepoviewPackage = properties.getProperty("domainRepoviewPackage");
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private String getSlowQueryLoggerLevel(IntrospectedTable introspectedTable) {
|
||||
String level = getTableProperty(introspectedTable, "slowQueryLoggerLevel", slowQueryLoggerLevel);
|
||||
if (!UtilTools.inArray(new String[]{"error", "warn", "debug", "info"}, level)) {
|
||||
return "error";
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("modelPackage"))) {
|
||||
modelPackage = properties.getProperty("modelPackage");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("mapperPackage"))) {
|
||||
mapperPackage = properties.getProperty("mapperPackage");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("targetProject"))) {
|
||||
targetProject = properties.getProperty("targetProject");
|
||||
}
|
||||
if (StringUtility.stringHasValue(properties.getProperty("viewKeyWords"))) {
|
||||
viewKeyWords = properties.getProperty("viewKeyWords").toUpperCase();
|
||||
return level;
|
||||
}
|
||||
|
||||
private String getSlowQueryLoggerTime(IntrospectedTable introspectedTable) {
|
||||
return getTableProperty(introspectedTable, "slowQueryLoggerTime", slowQueryLoggerTime);
|
||||
}
|
||||
|
||||
// ====================== 统一 Table 属性获取(你全类都能用) ======================
|
||||
private String getTableProperty(IntrospectedTable introspectedTable, String propName, String defaultValue) {
|
||||
try {
|
||||
TableConfiguration tc = introspectedTable.getTableConfiguration();
|
||||
String v = tc.getProperty(propName);
|
||||
if (StringUtility.stringHasValue(v)) {
|
||||
return v.trim();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,19 +102,16 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
@Override
|
||||
public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
|
||||
List<GeneratedJavaFile> generatedJavaFiles = new ArrayList<>();
|
||||
|
||||
// 仅处理视图表,非视图表直接返回
|
||||
String tableName = introspectedTable.getFullyQualifiedTable().getIntrospectedTableName().toUpperCase();
|
||||
if (!isViewTable(tableName)) {
|
||||
if (!ElementTools.isViewTable(introspectedTable)) {
|
||||
return generatedJavaFiles;
|
||||
}
|
||||
|
||||
// 1. 获取视图表元数据
|
||||
String domainObjectName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
|
||||
String exampleClassName = domainObjectName + "Example";
|
||||
String mapperClassName = domainObjectName + "Mapper";
|
||||
String repoInterfaceName = "I" + domainObjectName + "Repo";
|
||||
String repoImplName = domainObjectName + "RepoImpl";
|
||||
String repoInterfaceName = "I" + domainObjectName + domainViewRepositoryType;
|
||||
String repoImplName = domainObjectName + domainViewRepositoryType + "Impl";
|
||||
|
||||
boolean hasBLOBColumns = ElementTools.hasBLOBColumns(introspectedTable);
|
||||
|
||||
@@ -106,6 +127,7 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
|
||||
// 3. 生成视图Repo实现类
|
||||
TopLevelClass repoImpl = generateRepoViewImpl(
|
||||
introspectedTable,
|
||||
repoImplName,
|
||||
repoInterfaceName,
|
||||
domainObjectName,
|
||||
@@ -122,33 +144,17 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
generatedJavaFiles.add(implFile);
|
||||
|
||||
// 4. 手动写入磁盘(兼容1.4.1)
|
||||
generateJavaFileToDisk(repoInterface, facadeRepoviewPackage);
|
||||
generateJavaFileToDisk(repoImpl, domainRepoviewPackage);
|
||||
generateJavaFileToDisk(repoInterface, facadeViewRepositoryPackage);
|
||||
generateJavaFileToDisk(repoImpl, domainViewRepositoryPackage);
|
||||
|
||||
return generatedJavaFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为视图表(关键字匹配 + MBG原生视图配置)
|
||||
*/
|
||||
private boolean isViewTable(String tableName) {
|
||||
// 关键字匹配
|
||||
if (StringUtility.stringHasValue(viewKeyWords)) {
|
||||
String[] keywords = viewKeyWords.split(",");
|
||||
for (String keyword : keywords) {
|
||||
if (tableName.contains(keyword.trim().toUpperCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心修改:生成视图Repo接口(移除继承,手动添加指定方法)
|
||||
*/
|
||||
private Interface generateRepoViewInterface(String interfaceName, String modelClassName, String exampleClassName) {
|
||||
Interface repoInterface = new Interface(facadeRepoviewPackage + "." + interfaceName);
|
||||
Interface repoInterface = new Interface(facadeViewRepositoryPackage + "." + interfaceName);
|
||||
repoInterface.setVisibility(JavaVisibility.PUBLIC);
|
||||
|
||||
// 添加必要的导入包(仅保留model、example、List)
|
||||
@@ -183,6 +189,15 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
countMethod.setAbstract(true);
|
||||
repoInterface.addMethod(countMethod);
|
||||
|
||||
// 4. 添加countWithPage方法
|
||||
Method countWithPageMethod = new Method("countWithPage");
|
||||
countWithPageMethod.setVisibility(JavaVisibility.PUBLIC);
|
||||
countWithPageMethod.setReturnType(new FullyQualifiedJavaType("long"));
|
||||
countWithPageMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
countWithPageMethod.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
countWithPageMethod.setAbstract(true);
|
||||
repoInterface.addMethod(countWithPageMethod);
|
||||
|
||||
return repoInterface;
|
||||
}
|
||||
|
||||
@@ -190,6 +205,7 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
* 生成视图Repo实现类(逻辑不变,仅适配新接口)
|
||||
*/
|
||||
private TopLevelClass generateRepoViewImpl(
|
||||
IntrospectedTable introspectedTable,
|
||||
String implClassName,
|
||||
String interfaceName,
|
||||
String modelClassName,
|
||||
@@ -198,7 +214,9 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
boolean hasBLOBColumns
|
||||
) {
|
||||
|
||||
TopLevelClass implClass = new TopLevelClass(domainRepoviewPackage + "." + implClassName);
|
||||
String tableName = introspectedTable.getFullyQualifiedTable().getIntrospectedTableName();
|
||||
|
||||
TopLevelClass implClass = new TopLevelClass(domainViewRepositoryPackage + "." + implClassName);
|
||||
implClass.setVisibility(JavaVisibility.PUBLIC);
|
||||
implClass.addAnnotation("@SuppressWarnings(\"DuplicatedCode\")");
|
||||
implClass.addAnnotation("@Repository");
|
||||
@@ -207,7 +225,7 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
addImportPackages(implClass, modelClassName, exampleClassName, mapperClassName, interfaceName);
|
||||
|
||||
// 实现Repo接口
|
||||
FullyQualifiedJavaType superInterface = new FullyQualifiedJavaType(facadeRepoviewPackage + "." + interfaceName);
|
||||
FullyQualifiedJavaType superInterface = new FullyQualifiedJavaType(facadeViewRepositoryPackage + "." + interfaceName);
|
||||
implClass.addSuperInterface(superInterface);
|
||||
|
||||
// slow query logger
|
||||
@@ -225,12 +243,10 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
mapperField.addAnnotation("@Resource");
|
||||
implClass.addField(mapperField);
|
||||
|
||||
// 生成findOne方法
|
||||
generateFindOneMethod(implClass, modelClassName, exampleClassName, mapperFieldName);
|
||||
// 生成getList方法
|
||||
generateGetListMethod(implClass, modelClassName, exampleClassName, mapperFieldName, hasBLOBColumns);
|
||||
// 生成count方法
|
||||
generateCountMethod(implClass, exampleClassName, mapperFieldName);
|
||||
generateFindOneMethod(implClass, tableName, modelClassName, exampleClassName);
|
||||
generateGetListMethod(implClass, tableName, introspectedTable, modelClassName, exampleClassName, mapperFieldName, hasBLOBColumns);
|
||||
generateCountMethod(implClass, tableName, introspectedTable, modelClassName, exampleClassName, mapperFieldName);
|
||||
generateCountWithPageMethod(implClass, tableName, exampleClassName);
|
||||
|
||||
return implClass;
|
||||
}
|
||||
@@ -245,20 +261,20 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
implClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + modelClassName));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + exampleClassName));
|
||||
// Repo接口
|
||||
implClass.addImportedType(new FullyQualifiedJavaType(facadeRepoviewPackage + "." + interfaceName));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType(facadeViewRepositoryPackage + "." + interfaceName));
|
||||
// 注解&工具类
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("org.springframework.stereotype.Repository"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("javax.annotation.Resource"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("org.slf4j.Logger"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("org.slf4j.LoggerFactory"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("java.util.ArrayList"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("java.util.Date"));
|
||||
implClass.addImportedType(new FullyQualifiedJavaType("java.util.List"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成findOne方法
|
||||
*/
|
||||
private void generateFindOneMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName) {
|
||||
private void generateFindOneMethod(TopLevelClass implClass, String tableName, String modelClassName, String exampleClassName) {
|
||||
Method method = new Method("findOne");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
@@ -268,6 +284,8 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
// 方法体
|
||||
method.addBodyLine("// clone new example");
|
||||
method.addBodyLine("example = example.cloneExample();");
|
||||
method.addBodyLine("example.usePage(1, 1);");
|
||||
method.addBodyLine("List<" + modelClassName + "> dataList = getList(example);");
|
||||
method.addBodyLine("if (dataList != null && !dataList.isEmpty()) {");
|
||||
@@ -281,7 +299,7 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
/**
|
||||
* 生成getList方法
|
||||
*/
|
||||
private void generateGetListMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName, boolean hasBLOBColumns) {
|
||||
private void generateGetListMethod(TopLevelClass implClass, String tableName, IntrospectedTable introspectedTable, String modelClassName, String exampleClassName, String mapperFieldName, boolean hasBLOBColumns) {
|
||||
Method method = new Method("getList");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
@@ -289,29 +307,47 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
// 参数名匹配示例(首字母小写)
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
method.addBodyLine("// clone new example");
|
||||
method.addBodyLine("example = example.cloneExample();");
|
||||
method.addBodyLine("List<" + modelClassName + "> result = null;");
|
||||
method.addBodyLine("long startTime = new Date().getTime();");
|
||||
method.addBodyLine("try {");
|
||||
if (hasBLOBColumns) {
|
||||
method.addBodyLine("if (example.isWithBLOBs()) {");
|
||||
method.addBodyLine("return " + mapperFieldName + ".selectByExampleWithBLOBs(example);");
|
||||
method.addBodyLine("result = " + mapperFieldName + ".selectByExampleWithBLOBs(example);");
|
||||
method.addBodyLine("} else {");
|
||||
method.addBodyLine("result = " + mapperFieldName + ".selectByExample(example);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return " + mapperFieldName + ".selectByExample(example);");
|
||||
} else {
|
||||
method.addBodyLine("return " + mapperFieldName + ".selectByExample(example);");
|
||||
method.addBodyLine("result = " + mapperFieldName + ".selectByExample(example);");
|
||||
}
|
||||
method.addBodyLine("} finally {");
|
||||
method.addBodyLine("long useTime = new Date().getTime() - startTime;");
|
||||
method.addBodyLine("if (useTime > " + slowQueryLoggerTime + ") {");
|
||||
method.addBodyLine("LOGGER.error(\"get view list use long time: \" + useTime + \"ms\");");
|
||||
method.addBodyLine("if (useTime > " + getSlowQueryLoggerTime(introspectedTable) + ") {");
|
||||
method.addBodyLine("String exampleString = \"\";");
|
||||
method.addBodyLine("if (example.getWhereString() != null) {");
|
||||
method.addBodyLine("exampleString += \"\\n\\t|-> where: \" + example.getWhereString();");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("if (example.getOrderByClause() != null) {");
|
||||
method.addBodyLine("exampleString += \"\\n\\t|-> order by: \" + example.getOrderByClause();");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("if (example.getLimitString() != null) {");
|
||||
method.addBodyLine("exampleString += \"\\n\\t|-> limit: \" + example.getLimitString();");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("LOGGER." + getSlowQueryLoggerLevel(introspectedTable) + "(\"[SQL] select " + modelClassName + " view list long time\" +");
|
||||
method.addBodyLine(" \"\\n\\t|-> table name: " + tableName + "\" +");
|
||||
method.addBodyLine(" \"\\n\\t|-> use time: \" + useTime + \"ms\" +");
|
||||
method.addBodyLine(" exampleString +");
|
||||
method.addBodyLine(" \"\\n\\t|-----------------------------------\"");
|
||||
method.addBodyLine(");");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return result;");
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成count方法
|
||||
*/
|
||||
private void generateCountMethod(TopLevelClass implClass, String exampleClassName, String mapperFieldName) {
|
||||
private void generateCountMethod(TopLevelClass implClass, String tableName, IntrospectedTable introspectedTable, String modelClassName, String exampleClassName, String mapperFieldName) {
|
||||
Method method = new Method("count");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
@@ -321,15 +357,49 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
// 方法体
|
||||
method.addBodyLine("// clone new example");
|
||||
method.addBodyLine("example = example.cloneExample();");
|
||||
method.addBodyLine("long startTime = new Date().getTime();");
|
||||
method.addBodyLine("try {");
|
||||
method.addBodyLine("return " + mapperFieldName + ".countByExample(example);");
|
||||
method.addBodyLine("} finally {");
|
||||
method.addBodyLine("long count = " + mapperFieldName + ".countByExample(example);");
|
||||
method.addBodyLine("long useTime = new Date().getTime() - startTime;");
|
||||
method.addBodyLine("if (useTime > " + slowQueryLoggerTime + ") {");
|
||||
method.addBodyLine("LOGGER.error(\"count view use long time: \" + useTime + \"ms\");");
|
||||
method.addBodyLine("if (useTime > " + getSlowQueryLoggerTime(introspectedTable) + ") {");
|
||||
method.addBodyLine("String exampleString = \"\";");
|
||||
method.addBodyLine("if (example.getWhereString() != null) {");
|
||||
method.addBodyLine("exampleString += \"\\n\\t|-> where: \" + example.getWhereString();");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("if (example.getOrderByClause() != null) {");
|
||||
method.addBodyLine("exampleString += \"\\n\\t|-> order by: \" + example.getOrderByClause();");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("LOGGER." + getSlowQueryLoggerLevel(introspectedTable) + "(\"[SQL] select " + modelClassName + " view count long time\" +");
|
||||
method.addBodyLine(" \"\\n\\t|-> table name: " + tableName + "\" +");
|
||||
method.addBodyLine(" \"\\n\\t|-> use time: \" + useTime + \"ms\" +");
|
||||
method.addBodyLine(" exampleString +");
|
||||
method.addBodyLine(" \"\\n\\t|-----------------------------------\"");
|
||||
method.addBodyLine(");");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return count;");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成count方法
|
||||
*/
|
||||
private void generateCountWithPageMethod(TopLevelClass implClass, String tableName, String exampleClassName) {
|
||||
Method method = new Method("countWithPage");
|
||||
method.addAnnotation("@Override");
|
||||
method.setVisibility(JavaVisibility.PUBLIC);
|
||||
method.setReturnType(new FullyQualifiedJavaType("long"));
|
||||
// 参数名匹配示例(首字母小写)
|
||||
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
|
||||
method.addException(new FullyQualifiedJavaType("Throwable"));
|
||||
|
||||
// 方法体
|
||||
method.addBodyLine("// When not paginated, the count query returns 0 to avoid unnecessary queries");
|
||||
method.addBodyLine("if (example.getRows() != null && example.getOffset() != null) {");
|
||||
method.addBodyLine("return count(example);");
|
||||
method.addBodyLine("}");
|
||||
method.addBodyLine("return 0L;");
|
||||
|
||||
implClass.addMethod(method);
|
||||
}
|
||||
@@ -9,6 +9,17 @@ import static org.mybatis.generator.internal.util.messages.Messages.getString;
|
||||
@SuppressWarnings("unused")
|
||||
public class ElementTools {
|
||||
|
||||
/**
|
||||
* 判断IntrospectedTable是否代表数据库视图
|
||||
*
|
||||
* @param introspectedTable MBG内省表对象
|
||||
* @return true=视图,false=普通表/其他类型
|
||||
*/
|
||||
public static boolean isViewTable(IntrospectedTable introspectedTable) {
|
||||
String tableType = introspectedTable.getTableType();
|
||||
return "VIEW".equals(tableType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测数据表是否含有BLOB列数据
|
||||
*
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.iqudoo.framework.mybatis.utils;
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public class UtilTools {
|
||||
|
||||
public static <T> boolean inArray(T[] array, T target) {
|
||||
for (T val : array) {
|
||||
if (val != null && val.equals(target)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user