Compare commits

...

15 Commits

Author SHA1 Message Date
iqudoo
0cfaea99c4 v1 2026-04-21 02:52:14 +08:00
iqudoo
eea9e5e6ee v1 2026-04-21 02:51:02 +08:00
iqudoo
114f69597b 修复:外部传入的 Example 不会被内部修改,完全无副作用 2026-04-21 00:56:35 +08:00
iqudoo
0281b89803 fix 2026-04-16 21:47:07 +08:00
iqudoo
b4488bf7f3 修复bug 2026-04-16 19:38:36 +08:00
iqudoo
959486fed0 V1 2026-04-16 19:20:44 +08:00
iqudoo
c048da1faf 慢查询打印limit 2026-04-16 01:02:53 +08:00
iqudoo
b85966c535 支持添加数据变更日志 2026-04-15 00:46:34 +08:00
iqudoo
0bea5abfb6 优化:不依赖表前缀判断是否为视图 2026-04-13 02:06:41 +08:00
iqudoo
885f823203 优化超时日志 2026-04-13 01:43:26 +08:00
iqudoo
dc7ccf905f 批量插入 2026-04-12 19:07:12 +08:00
iqudoo
abfab32498 fix 2026-04-12 18:51:37 +08:00
iqudoo
6ecdf66eeb 日志优化 2026-04-12 16:24:12 +08:00
iqudoo
4bddff2de9 更新插件 2026-04-12 13:08:31 +08:00
iqudoo
a2e1fdd8e3 插件更新 2026-04-12 13:08:20 +08:00
7 changed files with 908 additions and 700 deletions

View File

@@ -5,10 +5,9 @@
本插件为 MyBatis Generator 提供了以下增强功能: 本插件为 MyBatis Generator 提供了以下增强功能:
1. **TapeMybatisGeneratorPlugin** - 扩展 MyBatis Mapper添加 `selectPrimaryKeyByExample` 方法,支持分页查询主键列表 1. **TapeMybatisGeneratorPlugin** - 扩展 MyBatis Mapper添加 `selectPrimaryKeyByExample`, `batchInsert` 方法,拓展查询分页支持
2. **TapeRepositoryGeneratorPlugin** - 为非视图表自动生成 Repository 接口和实现类,提供完整的 CRUD 和软删除功能 2. **TapeRepositoryGeneratorPlugin** - 为非视图表自动生成 Repository 接口和实现类,提供完整的 CRUD 和软删除功能
3. **TapeRepoviewGeneratorPlugin** - 为视图表自动生成 RepoView 接口和实现类,提供查询功能 3. **TapeRepoviewGeneratorPlugin** - 为视图表自动生成 RepoView 接口和实现类,提供查询功能
4. **分页支持** - 为 Example 类自动添加分页相关字段和方法offset、rows、usePage、limit 等)
## 插件说明 ## 插件说明
@@ -38,8 +37,11 @@
- `getValidList({Example} example)` - 获取有效记录列表(支持分页) - `getValidList({Example} example)` - 获取有效记录列表(支持分页)
- `getTrashList({Example} example)` - 获取回收站记录列表(支持分页) - `getTrashList({Example} example)` - 获取回收站记录列表(支持分页)
- `countByValid({Example} example)` - 统计有效记录数 - `countByValid({Example} example)` - 统计有效记录数
- `countByValidWithPage({Example} example)` - 统计分页有效记录数
- `countByTrash({Example} example)` - 统计回收站记录数 - `countByTrash({Example} example)` - 统计回收站记录数
- `countByTrashWithPage({Example} example)` - 统计分页回收站记录数
- `insert({Model} record)` - 插入记录(自动生成 GUID、设置默认值 - `insert({Model} record)` - 插入记录(自动生成 GUID、设置默认值
- `batchInsert(List<{Model}> records)` - 批量插入记录(自动生成 GUID、设置默认值
- `updateByExampleSelective({Model} record, {Example} example)` - 按条件更新记录 - `updateByExampleSelective({Model} record, {Example} example)` - 按条件更新记录
- `update({Model} record)` - 更新记录(支持乐观锁) - `update({Model} record)` - 更新记录(支持乐观锁)
@@ -60,9 +62,8 @@
**添加的字段** **添加的字段**
- `offset` - 偏移量 - `offset` - 偏移量
- `rows` - 每页数量 - `rows` - 每页数量
- `minPageNum` - 最小页码(默认 1 - `startPageNum` - 最小页码(默认 1
- `ignorePageSize` - 忽略分页数量(默认 10000每页数量大于10000时忽略分页 - `ignorePageSize` - 忽略分页数量(默认 10000每页数量大于10000时忽略分页
- `defaultPageSize` - 默认每页数量(默认 20
- `maxPageSize` - 最大每页数量(默认 100 - `maxPageSize` - 最大每页数量(默认 100
- `withBLOBs` - 是否返回BLOBs列的数据 - `withBLOBs` - 是否返回BLOBs列的数据
@@ -70,10 +71,12 @@
- `limit(int rows)` - 设置每页数量 - `limit(int rows)` - 设置每页数量
- `limit(int offset, int rows)` - 设置偏移量和每页数量 - `limit(int offset, int rows)` - 设置偏移量和每页数量
- `usePage(int pageNum, int pageSize)` - 使用页码和每页数量(自动计算 offset - `usePage(int pageNum, int pageSize)` - 使用页码和每页数量(自动计算 offset
- `getPageNum()` - 获取当前页码
- `getPageSize()` - 获取当前每页数量
- `setWithBLOBs(boolean withBLOBs)` - 设置是否返回BLOBs列的数据 - `setWithBLOBs(boolean withBLOBs)` - 设置是否返回BLOBs列的数据
- `isWithBLOBs()` - 是否返回BLOBs列的数据 - `isWithBLOBs()` - 是否返回BLOBs列的数据
- `getPageNum()` - 获取当前页码
- `getPageSize()` - 获取当前每页数量
- `getOffset()` - 获取当前分页limit的offset
- `getRows()` - 获取当前分页limit的rows
## 使用方法 ## 使用方法
### 1. 在 `pom.xml` 中配置插件 ### 1. 在 `pom.xml` 中配置插件
@@ -125,22 +128,27 @@
### 2. 在 `mybatis.generator.xml` 中配置插件 ### 2. 在 `mybatis.generator.xml` 中配置插件
```xml ```xml
<context id="Mysql" targetRuntime="MyBatis3"> <context id="Mysql" targetRuntime="MyBatis3">
<!-- 配置属性 --> <!-- 配置属性 -->
<property name="viewKeyWords" value="VIEW_,V_"/>
<property name="targetProject" value="src/main/java"/> <property name="targetProject" value="src/main/java"/>
<property name="modelPackage" value="com.iqudoo.platform.application.database.model"/> <property name="modelPackage" value="com.iqudoo.platform.application.database.model"/>
<property name="mapperPackage" value="com.iqudoo.platform.application.database.mapper"/> <property name="mapperPackage" value="com.iqudoo.platform.application.database.mapper"/>
<property name="facadeRepositoryPackage" value="com.iqudoo.platform.application.facade.repository"/> <property name="facadeRepositoryPackage" value="com.iqudoo.platform.application.facade.repository"/>
<property name="domainRepositoryPackage" value="com.iqudoo.platform.application.domain.repository"/> <property name="domainRepositoryPackage" value="com.iqudoo.platform.application.domain.repository"/>
<property name="facadeRepoviewPackage" value="com.iqudoo.platform.application.facade.repoview"/> <property name="facadeViewRepositoryPackage" value="com.iqudoo.platform.application.facade.repoview"/>
<property name="domainRepoviewPackage" value="com.iqudoo.platform.application.domain.repoview"/> <property name="domainViewRepositoryPackage" value="com.iqudoo.platform.application.domain.repoview"/>
<property name="snowflakeUtilClass" value="com.iqudoo.framework.tape.modules.utils.SnowflakeUtil"/> <property name="guidGeneratorClass" value="com.iqudoo.framework.tape.modules.utils.SnowflakeUtil"/>
<property name="snowflakeUtilGenId" value="SnowflakeUtil.nextId()"/> <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="true"/>
<property name="slowQueryLoggerTime" value="300"/> <property name="slowQueryLoggerTime" value="300"/>
<property name="slowQueryLoggerLevel" value="error"/>
<property name="optimisticLockEnable" value="true"/>
<property name="ignorePageSize" value="10000"/> <property name="ignorePageSize" value="10000"/>
<property name="defaultPageSize" value="20"/> <property name="startPageNum" value="1"/>
<property name="startPage" value="1"/> <property name="maxPageSize" value="100"/>
<!-- 添加插件 --> <!-- 添加插件 -->
<plugin type="com.iqudoo.framework.mybatis.TapeMybatisGeneratorPlugin"/> <plugin type="com.iqudoo.framework.mybatis.TapeMybatisGeneratorPlugin"/>
@@ -154,8 +162,7 @@
### 3. 配置参数说明 ### 3. 配置参数说明
| 参数名 | 说明 | 默认值 | 必需 | | 参数名 | 说明 | 默认值 | 必需 |
|--------|---------------------|---------------------------------------------------------|------| |----------------------------|-------------------------------|---------------------------------------------------------|------|
| `viewKeyWords` | 视图表关键字(逗号分隔,不区分大小写) | `VIEW_,V_` | 否 |
| `targetProject` | 生成代码的目标项目路径 | `src/main/java` | 否 | | `targetProject` | 生成代码的目标项目路径 | `src/main/java` | 否 |
| `modelPackage` | Model 类的包路径 | `com.iqudoo.platform.application.database.model` | 是 | | `modelPackage` | Model 类的包路径 | `com.iqudoo.platform.application.database.model` | 是 |
| `mapperPackage` | Mapper 接口的包路径 | `com.iqudoo.platform.application.database.mapper` | 是 | | `mapperPackage` | Mapper 接口的包路径 | `com.iqudoo.platform.application.database.mapper` | 是 |
@@ -164,15 +171,30 @@
| `facadeRepoviewPackage` | RepoView 接口的包路径 | `com.iqudoo.platform.application.facade.repoview` | 否 | | `facadeRepoviewPackage` | RepoView 接口的包路径 | `com.iqudoo.platform.application.facade.repoview` | 否 |
| `snowflakeUtilClass` | 雪花算法ID生成工具类 | `com.iqudoo.framework.tape.modules.utils.SnowflakeUtil` | 否 | | `snowflakeUtilClass` | 雪花算法ID生成工具类 | `com.iqudoo.framework.tape.modules.utils.SnowflakeUtil` | 否 |
| `snowflakeUtilGenId` | 雪花算法ID生成方法 | `SnowflakeUtil.nextId()` | 否 | | `snowflakeUtilGenId` | 雪花算法ID生成方法 | `SnowflakeUtil.nextId()` | 否 |
| `slowQueryLoggerTime` | 慢查询日志时间阈值 | `200` | 否 | | `changeLogContextClassPackage` | 变更日志上下文包路径 | `com.iqudoo.platform.application.domain.changeLog` | 否 |
| `changeLogContextClassName` | 变更日志上下文类 | `ChangeLogContext` | 否 |
| `changeLogEnable` | 变更日志监听开关 | `false` | 否 |
| `slowQueryLoggerTime` | 慢查询日志时间阈值 | `300` | 否 |
| `slowQueryLoggerLevel` | 慢查询日志类型errorwarndebuginfo | `error` | 否 |
| `ignorePageSize` | 忽略分页阈值 | `10000` | 否 | | `ignorePageSize` | 忽略分页阈值 | `10000` | 否 |
| `defaultPageSize` | 默认分页数量 | `20` | 否 | | `startPageNum` | 分页开始页码 | `1` | 否 |
| `startPage` | 开始页码 | `1` | 否 | | `maxPageSize` | 最大每页数量 | `100` | 否 |
**视图表识别规则** ## 变更日志监听
- 表名包含 `viewKeyWords` 中任一关键字的表将被识别为视图表,大小写不敏感
- 视图表会生成 RepoView不会生成 Repository ChangeLogContext应该提供以下实现的静态方法Repository实现中调用
- 非视图表会生成 Repository不会生成 RepoView ```java
public class ChangeLogContext {
/**
* 添加一条变更
*/
public static void addLog(String tableName, String eventType, Long dataGuid, Map<String, Object[]> fieldChanges) {
// your thing code
}
}
```
## 数据库表结构要求 ## 数据库表结构要求
@@ -180,7 +202,7 @@
为了使用完整的 Repository 功能(软删除、回收站等),表结构需要包含以下标准字段: 为了使用完整的 Repository 功能(软删除、回收站等),表结构需要包含以下标准字段:
```sql ```mysql
DROP TABLE IF EXISTS `your_table_name`; DROP TABLE IF EXISTS `your_table_name`;
CREATE TABLE `your_table_name` ( CREATE TABLE `your_table_name` (
`guid` bigint(0) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'GUID', `guid` bigint(0) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'GUID',
@@ -193,7 +215,15 @@ CREATE TABLE `your_table_name` (
`data_version` int(0) NOT NULL DEFAULT 0 COMMENT '数据版本', `data_version` int(0) NOT NULL DEFAULT 0 COMMENT '数据版本',
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间', `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
`update_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 PRIMARY KEY (`guid`) USING BTREE,
-- UNIQUE KEY `idx_unique_key` (`you unique key`,`delete_token`) USING BTREE,
-- KEY `idx_common_query` (
-- 等值查询字段,
-- `is_hidden`,`is_delete`,
-- 其他参与排序字段,
-- `create_time` desc,
-- `guid`) USING BTREE
KEY `idx_common_query` (`is_hidden`,`is_delete`,`create_time` desc,`guid`) USING BTREE
) ENGINE = InnoDB COMMENT = '你的表格备注' ROW_FORMAT = Dynamic; ) ENGINE = InnoDB COMMENT = '你的表格备注' ROW_FORMAT = Dynamic;
``` ```

View File

@@ -2,6 +2,7 @@ package com.iqudoo.framework.mybatis;
import com.iqudoo.framework.mybatis.utils.ElementTools; import com.iqudoo.framework.mybatis.utils.ElementTools;
import com.iqudoo.framework.mybatis.utils.FormatTools; import com.iqudoo.framework.mybatis.utils.FormatTools;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter; import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*; import org.mybatis.generator.api.dom.java.*;
@@ -9,93 +10,90 @@ import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document; import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement; import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement; import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.internal.util.StringUtility; import org.mybatis.generator.internal.util.StringUtility;
import java.util.List; import java.util.List;
import java.util.Properties;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class TapeMybatisGeneratorPlugin extends PluginAdapter { public class TapeMybatisGeneratorPlugin extends PluginAdapter {
private final static int DEFAULT_START_PAGE = 1; private int startPageNum = 1;
private final static int DEFAULT_PAGE_SIZE = 20; private int maxPageSize = 100;
private final static int DEFAULT_IGNORE_PAGE_SIZE = 10000; private int ignorePageSize = 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;
}
}
}
@Override @Override
public boolean validate(List<String> list) { public boolean validate(List<String> list) {
return true; 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;
}
}
@SuppressWarnings("DuplicatedCode")
@Override @Override
public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper(); FullyQualifiedJavaType integerType = new FullyQualifiedJavaType("java.lang.Integer");
// 添加 minPageNum、defaultPageSize、maxPageSize、ignorePageSize 字段 FullyQualifiedJavaType booleanType = new FullyQualifiedJavaType("java.lang.Boolean");
FullyQualifiedJavaType stringType = new FullyQualifiedJavaType("java.lang.String");
String domainObjectName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
String exampleClassName = domainObjectName + "Example";
// 添加 startPageNum、maxPageSize、ignorePageSize 字段
Field maxPageSizeField = ElementTools.generateField( Field maxPageSizeField = ElementTools.generateField(
"maxPageSize", "maxPageSize",
JavaVisibility.PROTECTED, JavaVisibility.PROTECTED,
integerWrapper, integerType,
"100" this.maxPageSize + ""
); );
topLevelClass.addField(maxPageSizeField); topLevelClass.addField(maxPageSizeField);
Field ignorePageSizeField = ElementTools.generateField( Field ignorePageSizeField = ElementTools.generateField(
"ignorePageSize", "ignorePageSize",
JavaVisibility.PROTECTED, JavaVisibility.PROTECTED,
integerWrapper, integerType,
this.ignorePageSize + "" this.ignorePageSize + ""
); );
topLevelClass.addField(ignorePageSizeField); topLevelClass.addField(ignorePageSizeField);
Field defaultPageSizeField = ElementTools.generateField( Field startPageNumField = ElementTools.generateField(
"defaultPageSize", "startPageNum",
JavaVisibility.PROTECTED, JavaVisibility.PROTECTED,
integerWrapper, integerType,
defaultPageSize + "" startPageNum + ""
); );
topLevelClass.addField(defaultPageSizeField); topLevelClass.addField(startPageNumField);
Field minPageNumField = ElementTools.generateField(
"minPageNum",
JavaVisibility.PROTECTED,
integerWrapper,
startPage + ""
);
topLevelClass.addField(minPageNumField);
// 添加offset和rows字段 // 添加offset和rows字段
Field offsetField = ElementTools.generateField( Field offsetField = ElementTools.generateField(
"offset", "offset",
JavaVisibility.PROTECTED, JavaVisibility.PROTECTED,
integerWrapper, integerType,
"null" "null"
); );
topLevelClass.addField(offsetField); topLevelClass.addField(offsetField);
@@ -103,7 +101,7 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
Field rowsField = ElementTools.generateField( Field rowsField = ElementTools.generateField(
"rows", "rows",
JavaVisibility.PROTECTED, JavaVisibility.PROTECTED,
integerWrapper, integerType,
"null" "null"
); );
topLevelClass.addField(rowsField); topLevelClass.addField(rowsField);
@@ -114,7 +112,7 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
Field withBLOBsField = ElementTools.generateField( Field withBLOBsField = ElementTools.generateField(
"withBLOBs", "withBLOBs",
JavaVisibility.PROTECTED, JavaVisibility.PROTECTED,
new FullyQualifiedJavaType("java.lang.Boolean"), booleanType,
"true" "true"
); );
topLevelClass.addField(withBLOBsField); topLevelClass.addField(withBLOBsField);
@@ -127,7 +125,6 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
FormatTools.addMethodWithBestPosition(topLevelClass, isWithBLOBsMethod); FormatTools.addMethodWithBestPosition(topLevelClass, isWithBLOBsMethod);
} }
// 增加getter && setter 方法 // 增加getter && setter 方法
Method mSetMaxPageSize = ElementTools.generateSetterMethod(maxPageSizeField); Method mSetMaxPageSize = ElementTools.generateSetterMethod(maxPageSizeField);
FormatTools.addMethodWithBestPosition(topLevelClass, mSetMaxPageSize); FormatTools.addMethodWithBestPosition(topLevelClass, mSetMaxPageSize);
@@ -141,78 +138,75 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
Method mGetIgnorePageSize = ElementTools.generateGetterMethod(ignorePageSizeField); Method mGetIgnorePageSize = ElementTools.generateGetterMethod(ignorePageSizeField);
FormatTools.addMethodWithBestPosition(topLevelClass, mGetIgnorePageSize); FormatTools.addMethodWithBestPosition(topLevelClass, mGetIgnorePageSize);
Method mSetDefaultPageSize = ElementTools.generateSetterMethod(defaultPageSizeField); Method mSetStartPageNum = ElementTools.generateSetterMethod(startPageNumField);
FormatTools.addMethodWithBestPosition(topLevelClass, mSetDefaultPageSize); FormatTools.addMethodWithBestPosition(topLevelClass, mSetStartPageNum);
Method mGetDefaultPageSize = ElementTools.generateGetterMethod(defaultPageSizeField); Method mGetStartPageNum = ElementTools.generateGetterMethod(startPageNumField);
FormatTools.addMethodWithBestPosition(topLevelClass, mGetDefaultPageSize); FormatTools.addMethodWithBestPosition(topLevelClass, mGetStartPageNum);
Method mSetMinPageNum = ElementTools.generateSetterMethod(minPageNumField);
FormatTools.addMethodWithBestPosition(topLevelClass, mSetMinPageNum);
Method mGetMinPageNum = ElementTools.generateGetterMethod(minPageNumField);
FormatTools.addMethodWithBestPosition(topLevelClass, mGetMinPageNum);
Method mSetOffset = ElementTools.generateSetterMethod(offsetField);
FormatTools.addMethodWithBestPosition(topLevelClass, mSetOffset);
Method mGetOffset = ElementTools.generateGetterMethod(offsetField);
FormatTools.addMethodWithBestPosition(topLevelClass, mGetOffset);
Method mSetRows = ElementTools.generateSetterMethod(rowsField);
FormatTools.addMethodWithBestPosition(topLevelClass, mSetRows);
Method mGetRows = ElementTools.generateGetterMethod(rowsField);
FormatTools.addMethodWithBestPosition(topLevelClass, mGetRows);
// 提供几个快捷方法 // 提供几个快捷方法
Method setLimit = ElementTools.generateMethod( Method setLimitByRows = ElementTools.generateMethod(
"limit", "limit",
JavaVisibility.PUBLIC, JavaVisibility.PUBLIC,
topLevelClass.getType(), topLevelClass.getType(),
new Parameter(integerWrapper, "rows") new Parameter(integerType, "rows")
); );
setLimit = ElementTools.generateMethodBody( setLimitByRows = ElementTools.generateMethodBody(
setLimit, setLimitByRows,
"this.offset = null;", "this.offset = null;",
"this.rows = rows;", "this.rows = rows;",
"return this;" "return this;"
); );
FormatTools.addMethodWithBestPosition(topLevelClass, setLimit); FormatTools.addMethodWithBestPosition(topLevelClass, setLimitByRows);
Method setLimit2 = ElementTools.generateMethod( Method setLimitByOffsetRows = ElementTools.generateMethod(
"limit", "limit",
JavaVisibility.PUBLIC, JavaVisibility.PUBLIC,
topLevelClass.getType(), topLevelClass.getType(),
new Parameter(integerWrapper, "offset"), new Parameter(integerType, "offset"),
new Parameter(integerWrapper, "rows") new Parameter(integerType, "rows")
); );
setLimit2 = ElementTools.generateMethodBody( setLimitByOffsetRows = ElementTools.generateMethodBody(
setLimit2, setLimitByOffsetRows,
"this.offset = offset;", "this.offset = offset;",
"this.rows = rows;", "this.rows = rows;",
"return this;" "return this;"
); );
FormatTools.addMethodWithBestPosition(topLevelClass, setLimit2); FormatTools.addMethodWithBestPosition(topLevelClass, setLimitByOffsetRows);
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);
Method usePage = ElementTools.generateMethod( Method usePage = ElementTools.generateMethod(
"usePage", "usePage",
JavaVisibility.PUBLIC, JavaVisibility.PUBLIC,
topLevelClass.getType(), topLevelClass.getType(),
new Parameter(integerWrapper, "pageNum"), new Parameter(integerType, "pageNum"),
new Parameter(integerWrapper, "pageSize") new Parameter(integerType, "pageSize")
); );
usePage = ElementTools.generateMethodBody( usePage = ElementTools.generateMethodBody(
usePage, usePage,
"pageSize = pageSize == null || pageSize <= 0 ? this.defaultPageSize : pageSize;", "pageSize = pageSize == null || pageSize <= 0 ? 1 : pageSize;",
"pageNum = pageNum == null || pageNum < this.minPageNum ? this.minPageNum : pageNum;", "pageNum = pageNum == null || pageNum < this.startPageNum ? this.startPageNum : pageNum;",
"if (pageSize >= this.ignorePageSize) {", "if (pageSize >= this.ignorePageSize) {",
"this.rows = null;", "this.rows = null;",
"this.offset = null;", "this.offset = null;",
"return this;", "return this;",
"}", "}",
"int cPageSize = pageSize > this.maxPageSize ? this.maxPageSize: pageSize;", "int cPageSize = pageSize > this.maxPageSize ? this.maxPageSize: pageSize;",
"this.offset = (pageNum - this.minPageNum) * cPageSize;", "this.offset = (pageNum - this.startPageNum) * cPageSize;",
"this.rows = cPageSize;", "this.rows = cPageSize;",
"return this;" "return this;"
); );
@@ -222,21 +216,21 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
Method getPageNum = ElementTools.generateMethod( Method getPageNum = ElementTools.generateMethod(
"getPageNum", "getPageNum",
JavaVisibility.PUBLIC, JavaVisibility.PUBLIC,
integerWrapper integerType
); );
getPageNum = ElementTools.generateMethodBody( getPageNum = ElementTools.generateMethodBody(
getPageNum, getPageNum,
"if (this.rows == null || this.offset == null || this.rows == 0) {", "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); FormatTools.addMethodWithBestPosition(topLevelClass, getPageNum);
// 计算获取当前每页数量 // 计算获取当前每页数量
Method getPageSize = ElementTools.generateMethod( Method getPageSize = ElementTools.generateMethod(
"getPageSize", "getPageSize",
JavaVisibility.PUBLIC, JavaVisibility.PUBLIC,
integerWrapper integerType
); );
getPageSize = ElementTools.generateMethodBody( getPageSize = ElementTools.generateMethodBody(
getPageSize, getPageSize,
@@ -247,14 +241,130 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
); );
FormatTools.addMethodWithBestPosition(topLevelClass, getPageSize); FormatTools.addMethodWithBestPosition(topLevelClass, getPageSize);
Method getRows = ElementTools.generateMethod(
"getRows",
JavaVisibility.PUBLIC,
integerType
);
getRows = ElementTools.generateMethodBody(
getRows,
"return this.rows;"
);
FormatTools.addMethodWithBestPosition(topLevelClass, getRows);
Method getOffset = ElementTools.generateMethod(
"getOffset",
JavaVisibility.PUBLIC,
integerType
);
getOffset = ElementTools.generateMethodBody(
getOffset,
"return this.offset;"
);
FormatTools.addMethodWithBestPosition(topLevelClass, getOffset);
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);
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);
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 = startPageNum;",
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的清理 // !!! clear 方法增加 offset 和 rows的清理
boolean hasClear = false;
List<Method> methodList = topLevelClass.getMethods(); List<Method> methodList = topLevelClass.getMethods();
for (Method method : methodList) { for (Method method : methodList) {
if (method.getName().equals("clear")) { if (method.getName().equals("clear")) {
method.addBodyLine("rows = null;"); method.addBodyLine("rows = null;");
method.addBodyLine("offset = null;"); method.addBodyLine("offset = null;");
hasClear = true;
} }
} }
if (!hasClear) {
Method clear = ElementTools.generateMethod(
"clear",
JavaVisibility.PUBLIC,
new FullyQualifiedJavaType("void")
);
clear = ElementTools.generateMethodBody(
clear,
"rows = null;",
"offset = null;"
);
FormatTools.addMethodWithBestPosition(topLevelClass, clear);
}
return true; return true;
} }
@@ -292,16 +402,76 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
element.addElement(ifLimitNotNullElement); 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.addImportedType(new FullyQualifiedJavaType("java.util.List"));
interfaceObj.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Param"));
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 ========================================== // ============================================ selectPrimaryKeyByExample ==========================================
@Override @Override
public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) { public boolean clientGenerated(Interface interfaceObj, IntrospectedTable introspectedTable) {
if (introspectedTable.getTargetRuntime() != IntrospectedTable.TargetRuntime.MYBATIS3) { if (introspectedTable.getTargetRuntime() != IntrospectedTable.TargetRuntime.MYBATIS3) {
return true; return super.clientGenerated(interfaceObj, introspectedTable);
} }
// 添加接口方法 addBatchInsertClientMethod(interfaceObj, introspectedTable);
if (introspectedTable.getPrimaryKeyColumns().size() <= 0) { if (introspectedTable.getPrimaryKeyColumns().size() <= 0) {
return true; return super.clientGenerated(interfaceObj, introspectedTable);
} }
// 获取主键列类型 // 获取主键列类型
FullyQualifiedJavaType primaryType = introspectedTable.getPrimaryKeyColumns().get(0) FullyQualifiedJavaType primaryType = introspectedTable.getPrimaryKeyColumns().get(0)
@@ -317,19 +487,20 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
method.setVisibility(JavaVisibility.PUBLIC); method.setVisibility(JavaVisibility.PUBLIC);
method.setReturnType(returnType); method.setReturnType(returnType);
method.addParameter(new Parameter(exampleType, "example")); method.addParameter(new Parameter(exampleType, "example"));
interfaze.addMethod(method); interfaceObj.addMethod(method);
return super.clientGenerated(interfaze, introspectedTable); return super.clientGenerated(interfaceObj, introspectedTable);
} }
@Override @Override
public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) { public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
if (introspectedTable.getTargetRuntime() != IntrospectedTable.TargetRuntime.MYBATIS3) { if (introspectedTable.getTargetRuntime() != IntrospectedTable.TargetRuntime.MYBATIS3) {
return true; return super.sqlMapDocumentGenerated(document, introspectedTable);
} }
addBatchInsertXmlElement(document, introspectedTable);
if (introspectedTable.getPrimaryKeyColumns().size() <= 0) { if (introspectedTable.getPrimaryKeyColumns().size() <= 0) {
return true; return super.sqlMapDocumentGenerated(document, introspectedTable);
} }
// 获取主键列名 // 获取主键列名
String primaryKeyColumn = introspectedTable.getPrimaryKeyColumns().get(0) String primaryKeyColumn = introspectedTable.getPrimaryKeyColumns().get(0)

View File

@@ -1,6 +1,7 @@
package com.iqudoo.framework.mybatis; package com.iqudoo.framework.mybatis;
import com.iqudoo.framework.mybatis.utils.ElementTools; 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.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.JavaFormatter; import org.mybatis.generator.api.JavaFormatter;
@@ -14,62 +15,60 @@ import java.io.File;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties;
@SuppressWarnings({"DuplicatedCode", "SpellCheckingInspection", "ExtractMethodRecommender"}) @SuppressWarnings({"DuplicatedCode", "SpellCheckingInspection", "ExtractMethodRecommender"})
public class TapeRepoviewGeneratorPlugin extends PluginAdapter { public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
// 视图Repo包配置可通过配置文件自定义 // 视图Repo包配置可通过配置文件自定义
private String slowQueryLoggerTime = "300"; private String slowQueryLoggerTime = "300";
private String facadeRepoviewPackage = "com.iqudoo.platform.application.facade.repoview"; private String slowQueryLoggerLevel = "error";
private String domainRepoviewPackage = "com.iqudoo.platform.application.domain.repoview";
private String modelPackage = "com.iqudoo.platform.application.database.model"; private String modelPackage = "com.iqudoo.platform.application.database.model";
private String mapperPackage = "com.iqudoo.platform.application.database.mapper"; 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 targetProject = "src/main/java"; private String targetProject = "src/main/java";
// 视图名称关键字(可配置)
private String viewKeyWords = "VIEW_,V_";
// 1.4.1版本专用格式化器 // 1.4.1版本专用格式化器
private JavaFormatter javaFormatter; private JavaFormatter javaFormatter;
@Override
public void setContext(Context context) {
super.setContext(context);
this.javaFormatter = new DefaultJavaFormatter();
this.javaFormatter.setContext(context);
}
@Override @Override
public boolean validate(List<String> warnings) { public boolean validate(List<String> warnings) {
return true; return true;
} }
@Override @Override
public void setProperties(Properties properties) { public void setContext(Context context) {
super.setProperties(properties); super.setContext(context);
// 读取自定义配置 this.javaFormatter = new DefaultJavaFormatter();
if (StringUtility.stringHasValue(properties.getProperty("slowQueryLoggerTime"))) { this.javaFormatter.setContext(context);
slowQueryLoggerTime = properties.getProperty("slowQueryLoggerTime"); resolveConfiguration();
} }
if (StringUtility.stringHasValue(properties.getProperty("facadeRepoviewPackage"))) {
facadeRepoviewPackage = properties.getProperty("facadeRepoviewPackage"); private void resolveConfiguration() {
slowQueryLoggerTime = stringConfig("slowQueryLoggerTime", slowQueryLoggerTime);
slowQueryLoggerLevel = stringConfig("slowQueryLoggerLevel", slowQueryLoggerLevel);
if (!UtilTools.inArray(new String[]{"error", "warn", "debug", "info"}, slowQueryLoggerLevel)) {
slowQueryLoggerLevel = "error";
} }
if (StringUtility.stringHasValue(properties.getProperty("domainRepoviewPackage"))) { facadeViewRepositoryPackage = stringConfig("facadeViewRepositoryPackage", facadeViewRepositoryPackage);
domainRepoviewPackage = properties.getProperty("domainRepoviewPackage"); domainViewRepositoryPackage = stringConfig("domainViewRepositoryPackage", domainViewRepositoryPackage);
modelPackage = stringConfig("modelPackage", modelPackage);
mapperPackage = stringConfig("mapperPackage", mapperPackage);
targetProject = stringConfig("targetProject", targetProject);
} }
if (StringUtility.stringHasValue(properties.getProperty("modelPackage"))) {
modelPackage = properties.getProperty("modelPackage"); private String stringConfig(String key, String defaultValue) {
String v = properties.getProperty(key);
if (StringUtility.stringHasValue(v)) {
return v;
} }
if (StringUtility.stringHasValue(properties.getProperty("mapperPackage"))) { if (context != null) {
mapperPackage = properties.getProperty("mapperPackage"); v = context.getProperty(key);
if (StringUtility.stringHasValue(v)) {
return v;
} }
if (StringUtility.stringHasValue(properties.getProperty("targetProject"))) {
targetProject = properties.getProperty("targetProject");
}
if (StringUtility.stringHasValue(properties.getProperty("viewKeyWords"))) {
viewKeyWords = properties.getProperty("viewKeyWords").toUpperCase();
} }
return defaultValue;
} }
/** /**
@@ -78,13 +77,10 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
@Override @Override
public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) { public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
List<GeneratedJavaFile> generatedJavaFiles = new ArrayList<>(); List<GeneratedJavaFile> generatedJavaFiles = new ArrayList<>();
// 仅处理视图表,非视图表直接返回 // 仅处理视图表,非视图表直接返回
String tableName = introspectedTable.getFullyQualifiedTable().getIntrospectedTableName().toUpperCase(); if (!ElementTools.isViewTable(introspectedTable)) {
if (!isViewTable(tableName)) {
return generatedJavaFiles; return generatedJavaFiles;
} }
// 1. 获取视图表元数据 // 1. 获取视图表元数据
String domainObjectName = introspectedTable.getFullyQualifiedTable().getDomainObjectName(); String domainObjectName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
String exampleClassName = domainObjectName + "Example"; String exampleClassName = domainObjectName + "Example";
@@ -122,33 +118,17 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
generatedJavaFiles.add(implFile); generatedJavaFiles.add(implFile);
// 4. 手动写入磁盘兼容1.4.1 // 4. 手动写入磁盘兼容1.4.1
generateJavaFileToDisk(repoInterface, facadeRepoviewPackage); generateJavaFileToDisk(repoInterface, facadeViewRepositoryPackage);
generateJavaFileToDisk(repoImpl, domainRepoviewPackage); generateJavaFileToDisk(repoImpl, domainViewRepositoryPackage);
return generatedJavaFiles; 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接口移除继承手动添加指定方法 * 核心修改生成视图Repo接口移除继承手动添加指定方法
*/ */
private Interface generateRepoViewInterface(String interfaceName, String modelClassName, String exampleClassName) { 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); repoInterface.setVisibility(JavaVisibility.PUBLIC);
// 添加必要的导入包仅保留model、example、List // 添加必要的导入包仅保留model、example、List
@@ -183,6 +163,15 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
countMethod.setAbstract(true); countMethod.setAbstract(true);
repoInterface.addMethod(countMethod); 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; return repoInterface;
} }
@@ -198,7 +187,7 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
boolean hasBLOBColumns boolean hasBLOBColumns
) { ) {
TopLevelClass implClass = new TopLevelClass(domainRepoviewPackage + "." + implClassName); TopLevelClass implClass = new TopLevelClass(domainViewRepositoryPackage + "." + implClassName);
implClass.setVisibility(JavaVisibility.PUBLIC); implClass.setVisibility(JavaVisibility.PUBLIC);
implClass.addAnnotation("@SuppressWarnings(\"DuplicatedCode\")"); implClass.addAnnotation("@SuppressWarnings(\"DuplicatedCode\")");
implClass.addAnnotation("@Repository"); implClass.addAnnotation("@Repository");
@@ -207,7 +196,7 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
addImportPackages(implClass, modelClassName, exampleClassName, mapperClassName, interfaceName); addImportPackages(implClass, modelClassName, exampleClassName, mapperClassName, interfaceName);
// 实现Repo接口 // 实现Repo接口
FullyQualifiedJavaType superInterface = new FullyQualifiedJavaType(facadeRepoviewPackage + "." + interfaceName); FullyQualifiedJavaType superInterface = new FullyQualifiedJavaType(facadeViewRepositoryPackage + "." + interfaceName);
implClass.addSuperInterface(superInterface); implClass.addSuperInterface(superInterface);
// slow query logger // slow query logger
@@ -225,12 +214,10 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
mapperField.addAnnotation("@Resource"); mapperField.addAnnotation("@Resource");
implClass.addField(mapperField); implClass.addField(mapperField);
// 生成findOne方法 generateFindOneMethod(implClass, modelClassName, exampleClassName);
generateFindOneMethod(implClass, modelClassName, exampleClassName, mapperFieldName);
// 生成getList方法
generateGetListMethod(implClass, modelClassName, exampleClassName, mapperFieldName, hasBLOBColumns); generateGetListMethod(implClass, modelClassName, exampleClassName, mapperFieldName, hasBLOBColumns);
// 生成count方法 generateCountMethod(implClass, modelClassName, exampleClassName, mapperFieldName);
generateCountMethod(implClass, exampleClassName, mapperFieldName); generateCountWithPageMethod(implClass, modelClassName, exampleClassName, mapperFieldName);
return implClass; return implClass;
} }
@@ -245,20 +232,20 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
implClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + modelClassName)); implClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + modelClassName));
implClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + exampleClassName)); implClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + exampleClassName));
// Repo接口 // 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("org.springframework.stereotype.Repository"));
implClass.addImportedType(new FullyQualifiedJavaType("javax.annotation.Resource")); implClass.addImportedType(new FullyQualifiedJavaType("javax.annotation.Resource"));
implClass.addImportedType(new FullyQualifiedJavaType("org.slf4j.Logger")); implClass.addImportedType(new FullyQualifiedJavaType("org.slf4j.Logger"));
implClass.addImportedType(new FullyQualifiedJavaType("org.slf4j.LoggerFactory")); 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")); implClass.addImportedType(new FullyQualifiedJavaType("java.util.List"));
} }
/** /**
* 生成findOne方法 * 生成findOne方法
*/ */
private void generateFindOneMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName) { private void generateFindOneMethod(TopLevelClass implClass, String modelClassName, String exampleClassName) {
Method method = new Method("findOne"); Method method = new Method("findOne");
method.addAnnotation("@Override"); method.addAnnotation("@Override");
method.setVisibility(JavaVisibility.PUBLIC); method.setVisibility(JavaVisibility.PUBLIC);
@@ -268,6 +255,8 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
method.addException(new FullyQualifiedJavaType("Throwable")); method.addException(new FullyQualifiedJavaType("Throwable"));
// 方法体 // 方法体
method.addBodyLine("// clone new example");
method.addBodyLine("example = example.cloneExample();");
method.addBodyLine("example.usePage(1, 1);"); method.addBodyLine("example.usePage(1, 1);");
method.addBodyLine("List<" + modelClassName + "> dataList = getList(example);"); method.addBodyLine("List<" + modelClassName + "> dataList = getList(example);");
method.addBodyLine("if (dataList != null && !dataList.isEmpty()) {"); method.addBodyLine("if (dataList != null && !dataList.isEmpty()) {");
@@ -289,29 +278,43 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
// 参数名匹配示例(首字母小写) // 参数名匹配示例(首字母小写)
method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example"));
method.addException(new FullyQualifiedJavaType("Throwable")); 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("long startTime = new Date().getTime();");
method.addBodyLine("try {");
if (hasBLOBColumns) { if (hasBLOBColumns) {
method.addBodyLine("if (example.isWithBLOBs()) {"); 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("}");
method.addBodyLine("return " + mapperFieldName + ".selectByExample(example);");
} else { } 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("long useTime = new Date().getTime() - startTime;");
method.addBodyLine("if (useTime > " + slowQueryLoggerTime + ") {"); method.addBodyLine("if (useTime > " + slowQueryLoggerTime + ") {");
method.addBodyLine("LOGGER.error(\"get view list use long time: \" + useTime + \"ms\");"); method.addBodyLine("String exampleString = \"\";");
method.addBodyLine("if (example.getWhereString() != null) {");
method.addBodyLine("exampleString += \"\\n\\t|-> where: \" + example.getWhereString();");
method.addBodyLine("}"); method.addBodyLine("}");
method.addBodyLine("if (example.getOrderByClause() != null) {");
method.addBodyLine("exampleString += \"\\n\\t|-> order by: \" + example.getOrderByClause();");
method.addBodyLine("}"); method.addBodyLine("}");
method.addBodyLine("LOGGER." + slowQueryLoggerLevel + "(\"[SQL] select " + modelClassName + " view list use long time\" +");
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); implClass.addMethod(method);
} }
/** /**
* 生成count方法 * 生成count方法
*/ */
private void generateCountMethod(TopLevelClass implClass, String exampleClassName, String mapperFieldName) { private void generateCountMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName) {
Method method = new Method("count"); Method method = new Method("count");
method.addAnnotation("@Override"); method.addAnnotation("@Override");
method.setVisibility(JavaVisibility.PUBLIC); method.setVisibility(JavaVisibility.PUBLIC);
@@ -321,15 +324,48 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter {
method.addException(new FullyQualifiedJavaType("Throwable")); method.addException(new FullyQualifiedJavaType("Throwable"));
// 方法体 // 方法体
method.addBodyLine("// clone new example");
method.addBodyLine("example = example.cloneExample();");
method.addBodyLine("long startTime = new Date().getTime();"); method.addBodyLine("long startTime = new Date().getTime();");
method.addBodyLine("try {"); method.addBodyLine("long count = " + mapperFieldName + ".countByExample(example);");
method.addBodyLine("return " + mapperFieldName + ".countByExample(example);");
method.addBodyLine("} finally {");
method.addBodyLine("long useTime = new Date().getTime() - startTime;"); method.addBodyLine("long useTime = new Date().getTime() - startTime;");
method.addBodyLine("if (useTime > " + slowQueryLoggerTime + ") {"); method.addBodyLine("if (useTime > " + slowQueryLoggerTime + ") {");
method.addBodyLine("LOGGER.error(\"count view use long time: \" + useTime + \"ms\");"); method.addBodyLine("String exampleString = \"\";");
method.addBodyLine("if (example.getWhereString() != null) {");
method.addBodyLine("exampleString += \"\\n\\t|-> where: \" + example.getWhereString();");
method.addBodyLine("}"); method.addBodyLine("}");
method.addBodyLine("if (example.getOrderByClause() != null) {");
method.addBodyLine("exampleString += \"\\n\\t|-> order by: \" + example.getOrderByClause();");
method.addBodyLine("}"); method.addBodyLine("}");
method.addBodyLine("LOGGER." + slowQueryLoggerLevel + "(\"[SQL] select " + modelClassName + " view count use long time\" +");
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 modelClassName, String exampleClassName, String mapperFieldName) {
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); implClass.addMethod(method);
} }

View File

@@ -9,6 +9,17 @@ import static org.mybatis.generator.internal.util.messages.Messages.getString;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class ElementTools { 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列数据 * 检测数据表是否含有BLOB列数据
* *

View File

@@ -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;
}
}