From 40afa2cea1d46649c230061871f20c9ca290db3a Mon Sep 17 00:00:00 2001 From: iqudoo Date: Sun, 5 Apr 2026 17:28:05 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=9F=E6=88=90=E7=9A=84=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=9C=A8exmaple=E9=87=8C=E9=9D=A2=E8=AE=BE?= =?UTF-8?q?=E7=BD=AEsetWithBOLBs=E6=8E=A7=E5=88=B6=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E6=98=AF=E5=90=A6=E8=BF=94=E5=9B=9E=E9=95=BF?= =?UTF-8?q?=E6=96=87=E6=9C=AC=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 13 - ...-mybatis-generator-plugin-1.0-SNAPSHOT.jar | Bin 31396 -> 30130 bytes .../mybatis/TapeMybatisGeneratorPlugin.java | 286 +++++++++++++++++- .../TapeRepositoryGeneratorPlugin.java | 204 +++++++------ .../mybatis/TapeRepoviewGeneratorPlugin.java | 66 ++-- .../abstracts/AbstractWithLimitPlugin.java | 261 ---------------- .../hook/ISelectSelectivePluginHook.java | 9 - .../framework/mybatis/utils/ElementTools.java | 16 + 8 files changed, 433 insertions(+), 422 deletions(-) delete mode 100644 src/main/java/com/iqudoo/framework/mybatis/abstracts/AbstractWithLimitPlugin.java delete mode 100644 src/main/java/com/iqudoo/framework/mybatis/hook/ISelectSelectivePluginHook.java diff --git a/pom.xml b/pom.xml index a0fbe36..a0238e2 100644 --- a/pom.xml +++ b/pom.xml @@ -55,19 +55,6 @@ - - org.apache.maven.plugins - maven-javadoc-plugin - 3.2.0 - - - attach-javadocs - - jar - - - - org.apache.maven.plugins maven-gpg-plugin diff --git a/releases/tape-mybatis-generator-plugin-1.0-SNAPSHOT.jar b/releases/tape-mybatis-generator-plugin-1.0-SNAPSHOT.jar index f7aabf6aba95017efe23ef20a01b21b37694816b..95206425f54a480d99ec107fa9a9851ef69fa520 100644 GIT binary patch delta 24922 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 Wap^z=G+ZcLDCt+zsiez4O#cNjhC%B9 diff --git a/src/main/java/com/iqudoo/framework/mybatis/TapeMybatisGeneratorPlugin.java b/src/main/java/com/iqudoo/framework/mybatis/TapeMybatisGeneratorPlugin.java index 6804699..e7214c0 100644 --- a/src/main/java/com/iqudoo/framework/mybatis/TapeMybatisGeneratorPlugin.java +++ b/src/main/java/com/iqudoo/framework/mybatis/TapeMybatisGeneratorPlugin.java @@ -1,15 +1,296 @@ package com.iqudoo.framework.mybatis; -import com.iqudoo.framework.mybatis.abstracts.AbstractWithLimitPlugin; +import com.iqudoo.framework.mybatis.utils.ElementTools; +import com.iqudoo.framework.mybatis.utils.FormatTools; import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.PluginAdapter; import org.mybatis.generator.api.dom.java.*; 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.internal.util.StringUtility; + +import java.util.List; +import java.util.Properties; @SuppressWarnings("unused") -public class TapeMybatisGeneratorPlugin extends AbstractWithLimitPlugin { +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; + } + } + } + + @Override + public boolean validate(List list) { + return true; + } + + @Override + public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper(); + // 添加 minPageNum、defaultPageSize、maxPageSize、ignorePageSize 字段 + Field maxPageSizeField = ElementTools.generateField( + "maxPageSize", + JavaVisibility.PROTECTED, + integerWrapper, + "100" + ); + topLevelClass.addField(maxPageSizeField); + + Field ignorePageSizeField = ElementTools.generateField( + "ignorePageSize", + JavaVisibility.PROTECTED, + integerWrapper, + this.ignorePageSize + "" + ); + topLevelClass.addField(ignorePageSizeField); + + Field defaultPageSizeField = ElementTools.generateField( + "defaultPageSize", + JavaVisibility.PROTECTED, + integerWrapper, + defaultPageSize + "" + ); + topLevelClass.addField(defaultPageSizeField); + + Field minPageNumField = ElementTools.generateField( + "minPageNum", + JavaVisibility.PROTECTED, + integerWrapper, + startPage + "" + ); + topLevelClass.addField(minPageNumField); + + // 添加offset和rows字段 + Field offsetField = ElementTools.generateField( + "offset", + JavaVisibility.PROTECTED, + integerWrapper, + "null" + ); + topLevelClass.addField(offsetField); + + Field rowsField = ElementTools.generateField( + "rows", + JavaVisibility.PROTECTED, + integerWrapper, + "null" + ); + topLevelClass.addField(rowsField); + + boolean hasBLOBColumns = ElementTools.hasBLOBColumns(introspectedTable); + + if (hasBLOBColumns) { + Field withBLOBsField = ElementTools.generateField( + "withBLOBs", + JavaVisibility.PROTECTED, + new FullyQualifiedJavaType("java.lang.Boolean"), + "true" + ); + topLevelClass.addField(withBLOBsField); + Method mSetWithBLOBs = ElementTools.generateSetterMethod(withBLOBsField); + FormatTools.addMethodWithBestPosition(topLevelClass, mSetWithBLOBs); + Method isWithBLOBsMethod = new Method("isWithBLOBs"); + isWithBLOBsMethod.setVisibility(JavaVisibility.PUBLIC); + isWithBLOBsMethod.setReturnType(new FullyQualifiedJavaType("boolean")); + isWithBLOBsMethod.addBodyLine("return this.withBLOBs != null && this.withBLOBs;"); + FormatTools.addMethodWithBestPosition(topLevelClass, isWithBLOBsMethod); + } + + + // 增加getter && setter 方法 + Method mSetMaxPageSize = ElementTools.generateSetterMethod(maxPageSizeField); + FormatTools.addMethodWithBestPosition(topLevelClass, mSetMaxPageSize); + + Method mGetMaxPageSize = ElementTools.generateGetterMethod(maxPageSizeField); + FormatTools.addMethodWithBestPosition(topLevelClass, mGetMaxPageSize); + + Method mSetIgnorePageSize = ElementTools.generateSetterMethod(ignorePageSizeField); + FormatTools.addMethodWithBestPosition(topLevelClass, mSetIgnorePageSize); + + Method mGetIgnorePageSize = ElementTools.generateGetterMethod(ignorePageSizeField); + FormatTools.addMethodWithBestPosition(topLevelClass, mGetIgnorePageSize); + + Method mSetDefaultPageSize = ElementTools.generateSetterMethod(defaultPageSizeField); + FormatTools.addMethodWithBestPosition(topLevelClass, mSetDefaultPageSize); + + Method mGetDefaultPageSize = ElementTools.generateGetterMethod(defaultPageSizeField); + FormatTools.addMethodWithBestPosition(topLevelClass, mGetDefaultPageSize); + + 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( + "limit", + JavaVisibility.PUBLIC, + topLevelClass.getType(), + new Parameter(integerWrapper, "rows") + ); + setLimit = ElementTools.generateMethodBody( + setLimit, + "this.offset = null;", + "this.rows = rows;", + "return this;" + ); + FormatTools.addMethodWithBestPosition(topLevelClass, setLimit); + + Method setLimit2 = ElementTools.generateMethod( + "limit", + JavaVisibility.PUBLIC, + topLevelClass.getType(), + new Parameter(integerWrapper, "offset"), + new Parameter(integerWrapper, "rows") + ); + setLimit2 = ElementTools.generateMethodBody( + setLimit2, + "this.offset = offset;", + "this.rows = rows;", + "return this;" + ); + FormatTools.addMethodWithBestPosition(topLevelClass, setLimit2); + + Method usePage = ElementTools.generateMethod( + "usePage", + JavaVisibility.PUBLIC, + topLevelClass.getType(), + new Parameter(integerWrapper, "pageNum"), + new Parameter(integerWrapper, "pageSize") + ); + usePage = ElementTools.generateMethodBody( + usePage, + "pageSize = pageSize == null || pageSize <= 0 ? this.defaultPageSize : pageSize;", + "pageNum = pageNum == null || pageNum < this.minPageNum ? this.minPageNum : 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.rows = cPageSize;", + "return this;" + ); + FormatTools.addMethodWithBestPosition(topLevelClass, usePage); + + // 计算获取当前页码 + Method getPageNum = ElementTools.generateMethod( + "getPageNum", + JavaVisibility.PUBLIC, + integerWrapper + ); + getPageNum = ElementTools.generateMethodBody( + getPageNum, + "if (this.rows == null || this.offset == null || this.rows == 0) {", + "return this.minPageNum;", + "}", + "return this.offset / this.rows + this.minPageNum;" + ); + FormatTools.addMethodWithBestPosition(topLevelClass, getPageNum); + // 计算获取当前每页数量 + Method getPageSize = ElementTools.generateMethod( + "getPageSize", + JavaVisibility.PUBLIC, + integerWrapper + ); + getPageSize = ElementTools.generateMethodBody( + getPageSize, + "if (this.rows == null) {", + "return this.ignorePageSize;", + "}", + "return this.rows;" + ); + FormatTools.addMethodWithBestPosition(topLevelClass, getPageSize); + + // !!! clear 方法增加 offset 和 rows的清理 + List methodList = topLevelClass.getMethods(); + for (Method method : methodList) { + if (method.getName().equals("clear")) { + method.addBodyLine("rows = null;"); + method.addBodyLine("offset = null;"); + } + } + return true; + } + + @Override + public boolean sqlMapSelectAllElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { + this.generateLimitElement(element); + return super.sqlMapSelectAllElementGenerated(element, introspectedTable); + } + + @Override + public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { + this.generateLimitElement(element); + return super.sqlMapSelectByExampleWithoutBLOBsElementGenerated(element, introspectedTable); + } + + @Override + public boolean sqlMapSelectByExampleWithBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { + this.generateLimitElement(element); + return super.sqlMapSelectByExampleWithBLOBsElementGenerated(element, introspectedTable); + } + + public void generateLimitElement(XmlElement element) { + XmlElement ifLimitNotNullElement = new XmlElement("if"); + ifLimitNotNullElement.addAttribute(new Attribute("test", "rows != null")); + // rows + XmlElement ifOffsetNotNullElement = new XmlElement("if"); + ifOffsetNotNullElement.addAttribute(new Attribute("test", "offset != null")); + ifOffsetNotNullElement.addElement(new TextElement("limit ${offset}, ${rows}")); + ifLimitNotNullElement.addElement(ifOffsetNotNullElement); + // offset + XmlElement ifOffsetNullElement = new XmlElement("if"); + ifOffsetNullElement.addAttribute(new Attribute("test", "offset == null")); + ifOffsetNullElement.addElement(new TextElement("limit ${rows}")); + ifLimitNotNullElement.addElement(ifOffsetNullElement); + element.addElement(ifLimitNotNullElement); + } // ============================================ selectPrimaryKeyByExample ========================================== @@ -87,5 +368,4 @@ public class TapeMybatisGeneratorPlugin extends AbstractWithLimitPlugin { return super.sqlMapDocumentGenerated(document, introspectedTable); } - } diff --git a/src/main/java/com/iqudoo/framework/mybatis/TapeRepositoryGeneratorPlugin.java b/src/main/java/com/iqudoo/framework/mybatis/TapeRepositoryGeneratorPlugin.java index ada0eea..ed2a347 100644 --- a/src/main/java/com/iqudoo/framework/mybatis/TapeRepositoryGeneratorPlugin.java +++ b/src/main/java/com/iqudoo/framework/mybatis/TapeRepositoryGeneratorPlugin.java @@ -1,5 +1,6 @@ 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.*; @@ -15,7 +16,7 @@ import java.util.Properties; /** * MyBatis Generator 1.4.1 */ -@SuppressWarnings({"DuplicatedCode", "unused"}) +@SuppressWarnings({"DuplicatedCode", "unused", "SpellCheckingInspection"}) public class TapeRepositoryGeneratorPlugin extends PluginAdapter { // 固定配置项 @@ -92,7 +93,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { String mapperClassName = domainObjectName + "Mapper"; String repositoryInterfaceName = "I" + domainObjectName + "Repository"; String repositoryImplName = domainObjectName + "RepositoryImpl"; - boolean hasBLOBColumns = hasBLOBColumns(introspectedTable); + boolean hasBLOBColumns = ElementTools.hasBLOBColumns(introspectedTable); // 生成Repository接口(核心修改:手动添加所有方法,不再继承父接口) Interface repositoryInterface = generateRepositoryInterface(repositoryInterfaceName, domainObjectName, exampleClassName); @@ -156,9 +157,6 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { repositoryInterface.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + exampleClassName)); repositoryInterface.addImportedType(new FullyQualifiedJavaType("java.util.List")); - // 定义方法参数名(首字母小写) - String exampleParamName = lowerFirst(exampleClassName); - // 1. trashById Method trashByIdMethod = new Method("trashById"); trashByIdMethod.setVisibility(JavaVisibility.PUBLIC); @@ -172,7 +170,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { Method trashAllMethod = new Method("trashAll"); trashAllMethod.setVisibility(JavaVisibility.PUBLIC); trashAllMethod.setReturnType(new FullyQualifiedJavaType("int")); - trashAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + trashAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); trashAllMethod.addException(new FullyQualifiedJavaType("Throwable")); trashAllMethod.setAbstract(true); repositoryInterface.addMethod(trashAllMethod); @@ -191,7 +189,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { Method deleteAllMethod = new Method("deleteAll"); deleteAllMethod.setVisibility(JavaVisibility.PUBLIC); deleteAllMethod.setReturnType(new FullyQualifiedJavaType("int")); - deleteAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + deleteAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); deleteAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType("boolean"), "release")); deleteAllMethod.addException(new FullyQualifiedJavaType("Throwable")); deleteAllMethod.setAbstract(true); @@ -210,7 +208,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { Method recoverAllMethod = new Method("recoverAll"); recoverAllMethod.setVisibility(JavaVisibility.PUBLIC); recoverAllMethod.setReturnType(new FullyQualifiedJavaType("int")); - recoverAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + recoverAllMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); recoverAllMethod.addException(new FullyQualifiedJavaType("Throwable")); recoverAllMethod.setAbstract(true); repositoryInterface.addMethod(recoverAllMethod); @@ -246,7 +244,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { Method findValidOneMethod = new Method("findValidOne"); findValidOneMethod.setVisibility(JavaVisibility.PUBLIC); findValidOneMethod.setReturnType(new FullyQualifiedJavaType(modelClassName)); - findValidOneMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + findValidOneMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); findValidOneMethod.addException(new FullyQualifiedJavaType("Throwable")); findValidOneMethod.setAbstract(true); repositoryInterface.addMethod(findValidOneMethod); @@ -255,7 +253,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { Method findTrashOneMethod = new Method("findTrashOne"); findTrashOneMethod.setVisibility(JavaVisibility.PUBLIC); findTrashOneMethod.setReturnType(new FullyQualifiedJavaType(modelClassName)); - findTrashOneMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + findTrashOneMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); findTrashOneMethod.addException(new FullyQualifiedJavaType("Throwable")); findTrashOneMethod.setAbstract(true); repositoryInterface.addMethod(findTrashOneMethod); @@ -264,7 +262,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { Method getValidListMethod = new Method("getValidList"); getValidListMethod.setVisibility(JavaVisibility.PUBLIC); getValidListMethod.setReturnType(new FullyQualifiedJavaType("List<" + modelClassName + ">")); - getValidListMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + getValidListMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); getValidListMethod.addException(new FullyQualifiedJavaType("Throwable")); getValidListMethod.setAbstract(true); repositoryInterface.addMethod(getValidListMethod); @@ -273,7 +271,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { Method getTrashListMethod = new Method("getTrashList"); getTrashListMethod.setVisibility(JavaVisibility.PUBLIC); getTrashListMethod.setReturnType(new FullyQualifiedJavaType("List<" + modelClassName + ">")); - getTrashListMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + getTrashListMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); getTrashListMethod.addException(new FullyQualifiedJavaType("Throwable")); getTrashListMethod.setAbstract(true); repositoryInterface.addMethod(getTrashListMethod); @@ -282,7 +280,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { Method countByValidMethod = new Method("countByValid"); countByValidMethod.setVisibility(JavaVisibility.PUBLIC); countByValidMethod.setReturnType(new FullyQualifiedJavaType("long")); - countByValidMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + countByValidMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); countByValidMethod.addException(new FullyQualifiedJavaType("Throwable")); countByValidMethod.setAbstract(true); repositoryInterface.addMethod(countByValidMethod); @@ -291,7 +289,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { Method countByTrashMethod = new Method("countByTrash"); countByTrashMethod.setVisibility(JavaVisibility.PUBLIC); countByTrashMethod.setReturnType(new FullyQualifiedJavaType("long")); - countByTrashMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + countByTrashMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); countByTrashMethod.addException(new FullyQualifiedJavaType("Throwable")); countByTrashMethod.setAbstract(true); repositoryInterface.addMethod(countByTrashMethod); @@ -373,22 +371,21 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addAnnotation("@Override"); method.setVisibility(JavaVisibility.PUBLIC); method.setReturnType(new FullyQualifiedJavaType("int")); - String exampleParamName = lowerFirst(exampleClassName); - method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + 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(" + exampleParamName + ");"); + method.addBodyLine("return " + mapperFieldName + ".deleteByExample(example);"); method.addBodyLine("}"); - method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : " + exampleParamName + ".getOredCriteria()) {"); - method.addBodyLine(" criteria.andIsDeleteEqualTo(0);"); + method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {"); + method.addBodyLine("criteria.andIsDeleteEqualTo(0);"); 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) + ", " + exampleParamName + ");"); + method.addBodyLine("return " + mapperFieldName + ".updateByExampleSelective(" + lowerFirst(modelClassName) + ", example);"); implClass.addMethod(method); } @@ -398,20 +395,19 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addAnnotation("@Override"); method.setVisibility(JavaVisibility.PUBLIC); method.setReturnType(new FullyQualifiedJavaType("int")); - String exampleParamName = lowerFirst(exampleClassName); - method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); method.addException(new FullyQualifiedJavaType("Throwable")); // 方法体 - method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : " + exampleParamName + ".getOredCriteria()) {"); - method.addBodyLine(" criteria.andIsDeleteEqualTo(0);"); - method.addBodyLine(" criteria.andIsHiddenEqualTo(0);"); + method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {"); + method.addBodyLine("criteria.andIsDeleteEqualTo(0);"); + method.addBodyLine("criteria.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) + ", " + exampleParamName + ");"); + method.addBodyLine("return " + mapperFieldName + ".updateByExampleSelective(" + lowerFirst(modelClassName) + ", example);"); implClass.addMethod(method); } @@ -421,20 +417,19 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addAnnotation("@Override"); method.setVisibility(JavaVisibility.PUBLIC); method.setReturnType(new FullyQualifiedJavaType("int")); - String exampleParamName = lowerFirst(exampleClassName); - method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); method.addException(new FullyQualifiedJavaType("Throwable")); // 方法体 - method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : " + exampleParamName + ".getOredCriteria()) {"); - method.addBodyLine(" criteria.andIsDeleteEqualTo(0);"); - method.addBodyLine(" criteria.andIsHiddenEqualTo(1);"); + method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {"); + method.addBodyLine("criteria.andIsDeleteEqualTo(0);"); + method.addBodyLine("criteria.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) + ", " + exampleParamName + ");"); + method.addBodyLine("return " + mapperFieldName + ".updateByExampleSelective(" + lowerFirst(modelClassName) + ", example);"); implClass.addMethod(method); } @@ -480,15 +475,6 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { } } - private boolean hasBLOBColumns(IntrospectedTable introspectedTable) { - for (IntrospectedColumn column : introspectedTable.getAllColumns()) { - if (column.isBLOBColumn()) { - return true; - } - } - return false; - } - private void addImportPackages(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperClassName, String interfaceName) { implClass.addImportedType(new FullyQualifiedJavaType(snowflakeUtilClass)); implClass.addImportedType(new FullyQualifiedJavaType(mapperPackage + "." + mapperClassName)); @@ -512,7 +498,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addBodyLine(modelClassName + " aDo = " + mapperFieldName + ".selectByPrimaryKey(id);"); method.addBodyLine("if (aDo != null && aDo.getIsDelete() == 1) {"); - method.addBodyLine(" return null;"); + method.addBodyLine("return null;"); method.addBodyLine("}"); method.addBodyLine("return aDo;"); @@ -529,7 +515,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addBodyLine(modelClassName + " aDo = " + mapperFieldName + ".selectByPrimaryKey(id);"); method.addBodyLine("if (aDo != null && (aDo.getIsDelete() == 1 || aDo.getIsHidden() == 1)) {"); - method.addBodyLine(" return null;"); + method.addBodyLine("return null;"); method.addBodyLine("}"); method.addBodyLine("return aDo;"); @@ -546,7 +532,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addBodyLine(modelClassName + " aDo = " + mapperFieldName + ".selectByPrimaryKey(id);"); method.addBodyLine("if (aDo != null && (aDo.getIsDelete() == 1 || aDo.getIsHidden() == 0)) {"); - method.addBodyLine(" return null;"); + method.addBodyLine("return null;"); method.addBodyLine("}"); method.addBodyLine("return aDo;"); @@ -563,10 +549,10 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addBodyLine(modelClassName + " aDo = new " + modelClassName + "();"); method.addBodyLine("if (record.getGuid() != null) {"); - method.addBodyLine(" aDo.setGuid(record.getGuid());"); + method.addBodyLine("aDo.setGuid(record.getGuid());"); method.addBodyLine("} else {"); - method.addBodyLine(" Long guid = " + snowflakeUtilGenId + ";"); - method.addBodyLine(" aDo.setGuid(guid);"); + method.addBodyLine("Long guid = " + snowflakeUtilGenId + ";"); + method.addBodyLine("aDo.setGuid(guid);"); method.addBodyLine("}"); for (IntrospectedColumn column : introspectedTable.getAllColumns()) { @@ -591,7 +577,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addBodyLine("int count = " + mapperFieldName + ".insert(aDo);"); method.addBodyLine("if (count > 0) {"); - method.addBodyLine(" return aDo;"); + method.addBodyLine("return aDo;"); method.addBodyLine("}"); method.addBodyLine("// optimistic locking with data version and guid"); @@ -615,7 +601,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { 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("throw new Throwable(\"Database record not found, " + modelClassName + " GUID:\" + record.getGuid());"); method.addBodyLine("}"); for (IntrospectedColumn column : introspectedTable.getAllColumns()) { @@ -629,18 +615,18 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { continue; } method.addBodyLine("if (record." + getterMethod + "() != null) {"); - method.addBodyLine(" aDo." + setterMethod + "(record." + getterMethod + "());"); + 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("lockDataVersion = aDo.getDataVersion();"); method.addBodyLine("}"); method.addBodyLine("updateWhere.createCriteria()"); - method.addBodyLine(" .andGuidEqualTo(aDo.getGuid())"); - method.addBodyLine(" .andDataVersionEqualTo(lockDataVersion);"); + 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"); @@ -664,10 +650,10 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addBodyLine(modelClassName + " aDo = findValidById(id);"); method.addBodyLine("if (aDo == null) {"); - method.addBodyLine(" return 0;"); + method.addBodyLine("return 0;"); method.addBodyLine("}"); method.addBodyLine("if (release) {"); - method.addBodyLine(" return " + mapperFieldName + ".deleteByPrimaryKey(aDo.getGuid());"); + method.addBodyLine("return " + mapperFieldName + ".deleteByPrimaryKey(aDo.getGuid());"); method.addBodyLine("}"); method.addBodyLine("aDo.setIsDelete(1);"); method.addBodyLine("aDo.setUpdateTime(new Date());"); @@ -686,7 +672,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addBodyLine(modelClassName + " aDo = findValidById(id);"); method.addBodyLine("if (aDo == null) {"); - method.addBodyLine(" return 0;"); + method.addBodyLine("return 0;"); method.addBodyLine("}"); method.addBodyLine("aDo.setIsHidden(1);"); method.addBodyLine("aDo.setDeleteToken(aDo.getGuid() + \"\");"); @@ -706,10 +692,10 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addBodyLine(modelClassName + " aDo = findTrashById(id);"); method.addBodyLine("if (aDo == null) {"); - method.addBodyLine(" return 0;"); + method.addBodyLine("return 0;"); method.addBodyLine("}"); method.addBodyLine("if (aDo.getIsDelete() == 1) {"); - method.addBodyLine(" return 0;"); + method.addBodyLine("return 0;"); method.addBodyLine("}"); method.addBodyLine("aDo.setIsHidden(0);"); method.addBodyLine("aDo.setDeleteToken(\"VALID\");"); @@ -724,14 +710,13 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addAnnotation("@Override"); method.setVisibility(JavaVisibility.PUBLIC); method.setReturnType(new FullyQualifiedJavaType(modelClassName)); - String exampleParamName = exampleClassName.substring(0, 1).toLowerCase() + exampleClassName.substring(1); - method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); method.addException(new FullyQualifiedJavaType("Throwable")); - method.addBodyLine(exampleParamName + ".usePage(1, 1);"); - method.addBodyLine("List<" + modelClassName + "> dataList = getValidList(" + exampleParamName + ");"); - method.addBodyLine("if (dataList != null && dataList.size() > 0) {"); - method.addBodyLine(" return dataList.get(0);"); + 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;"); @@ -743,14 +728,13 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addAnnotation("@Override"); method.setVisibility(JavaVisibility.PUBLIC); method.setReturnType(new FullyQualifiedJavaType(modelClassName)); - String exampleParamName = exampleClassName.substring(0, 1).toLowerCase() + exampleClassName.substring(1); - method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); method.addException(new FullyQualifiedJavaType("Throwable")); - method.addBodyLine(exampleParamName + ".usePage(1, 1);"); - method.addBodyLine("List<" + modelClassName + "> dataList = getTrashList(" + exampleParamName + ");"); - method.addBodyLine("if (dataList != null && dataList.size() > 0) {"); - method.addBodyLine(" return dataList.get(0);"); + 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;"); @@ -767,23 +751,34 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addException(new FullyQualifiedJavaType("Throwable")); method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {"); - method.addBodyLine(" criteria.andIsDeleteEqualTo(0)"); - method.addBodyLine(" .andIsHiddenEqualTo(0);"); + method.addBodyLine("criteria.andIsDeleteEqualTo(0)"); + method.addBodyLine(".andIsHiddenEqualTo(0);"); method.addBodyLine("}"); method.addBodyLine("if (example.getRows() != null && example.getOffset() != null) {"); - method.addBodyLine(" List primaryKeyList = " + mapperFieldName + ".selectPrimaryKeyByExample(example);"); - method.addBodyLine(" if (primaryKeyList == null || primaryKeyList.size() == 0) {"); - method.addBodyLine(" return new ArrayList<>();"); - method.addBodyLine(" }"); - method.addBodyLine(" String oldOrderByClause = example.getOrderByClause();"); - method.addBodyLine(" example = new " + exampleClassName + "();"); - method.addBodyLine(" example.createCriteria().andGuidIn(primaryKeyList);"); - method.addBodyLine(" example.setOrderByClause(oldOrderByClause);"); + method.addBodyLine("List primaryKeyList = " + mapperFieldName + ".selectPrimaryKeyByExample(example);"); + method.addBodyLine("if (primaryKeyList == null || primaryKeyList.isEmpty()) {"); + method.addBodyLine("return new ArrayList<>();"); + 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("}"); - String selectMethod = hasBLOBColumns ? "selectByExampleWithBLOBs" : "selectByExample"; - method.addBodyLine("return " + mapperFieldName + "." + selectMethod + "(example);"); - + 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);"); + } implClass.addMethod(method); } @@ -797,23 +792,34 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addException(new FullyQualifiedJavaType("Throwable")); method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {"); - method.addBodyLine(" criteria.andIsDeleteEqualTo(0)"); - method.addBodyLine(" .andIsHiddenEqualTo(1);"); + method.addBodyLine("criteria.andIsDeleteEqualTo(0)"); + method.addBodyLine(".andIsHiddenEqualTo(1);"); method.addBodyLine("}"); method.addBodyLine("if (example.getRows() != null && example.getOffset() != null) {"); - method.addBodyLine(" List primaryKeyList = " + mapperFieldName + ".selectPrimaryKeyByExample(example);"); - method.addBodyLine(" if (primaryKeyList == null || primaryKeyList.size() == 0) {"); - method.addBodyLine(" return new ArrayList<>();"); - method.addBodyLine(" }"); - method.addBodyLine(" String oldOrderByClause = example.getOrderByClause();"); - method.addBodyLine(" example = new " + exampleClassName + "();"); - method.addBodyLine(" example.createCriteria().andGuidIn(primaryKeyList);"); - method.addBodyLine(" example.setOrderByClause(oldOrderByClause);"); + method.addBodyLine("List primaryKeyList = " + mapperFieldName + ".selectPrimaryKeyByExample(example);"); + method.addBodyLine("if (primaryKeyList == null || primaryKeyList.isEmpty()) {"); + method.addBodyLine("return new ArrayList<>();"); + 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("}"); - String selectMethod = hasBLOBColumns ? "selectByExampleWithBLOBs" : "selectByExample"; - method.addBodyLine("return " + mapperFieldName + "." + selectMethod + "(example);"); - + 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);"); + } implClass.addMethod(method); } @@ -826,8 +832,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addException(new FullyQualifiedJavaType("Throwable")); method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {"); - method.addBodyLine(" criteria.andIsDeleteEqualTo(0)"); - method.addBodyLine(" .andIsHiddenEqualTo(0);"); + method.addBodyLine("criteria.andIsDeleteEqualTo(0).andIsHiddenEqualTo(0);"); method.addBodyLine("}"); method.addBodyLine("return " + mapperFieldName + ".countByExample(example);"); @@ -843,8 +848,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter { method.addException(new FullyQualifiedJavaType("Throwable")); method.addBodyLine("for (" + exampleClassName + ".Criteria criteria : example.getOredCriteria()) {"); - method.addBodyLine(" criteria.andIsDeleteEqualTo(0)"); - method.addBodyLine(" .andIsHiddenEqualTo(1);"); + method.addBodyLine("criteria.andIsDeleteEqualTo(0).andIsHiddenEqualTo(1);"); method.addBodyLine("}"); method.addBodyLine("return " + mapperFieldName + ".countByExample(example);"); diff --git a/src/main/java/com/iqudoo/framework/mybatis/TapeRepoviewGeneratorPlugin.java b/src/main/java/com/iqudoo/framework/mybatis/TapeRepoviewGeneratorPlugin.java index 75e4952..1c531e2 100644 --- a/src/main/java/com/iqudoo/framework/mybatis/TapeRepoviewGeneratorPlugin.java +++ b/src/main/java/com/iqudoo/framework/mybatis/TapeRepoviewGeneratorPlugin.java @@ -1,5 +1,6 @@ package com.iqudoo.framework.mybatis; +import com.iqudoo.framework.mybatis.utils.ElementTools; import org.mybatis.generator.api.GeneratedJavaFile; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.JavaFormatter; @@ -18,7 +19,7 @@ import java.util.Properties; /** * MyBatis Generator 1.4.1 适配版:视图表专用 RepoView 生成插件 */ -@SuppressWarnings("DuplicatedCode") +@SuppressWarnings({"DuplicatedCode", "SpellCheckingInspection"}) public class TapeRepoviewGeneratorPlugin extends PluginAdapter { // 视图Repo包配置(可通过配置文件自定义) @@ -90,6 +91,8 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { String repoInterfaceName = "I" + domainObjectName + "Repo"; String repoImplName = domainObjectName + "RepoImpl"; + boolean hasBLOBColumns = ElementTools.hasBLOBColumns(introspectedTable); + // 2. 生成视图Repo接口(核心修改:移除继承,手动添加方法) Interface repoInterface = generateRepoViewInterface(repoInterfaceName, domainObjectName, exampleClassName); GeneratedJavaFile interfaceFile = new GeneratedJavaFile( @@ -106,7 +109,8 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { repoInterfaceName, domainObjectName, exampleClassName, - mapperClassName + mapperClassName, + hasBLOBColumns ); GeneratedJavaFile implFile = new GeneratedJavaFile( repoImpl, @@ -151,14 +155,11 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { repoInterface.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + exampleClassName)); repoInterface.addImportedType(new FullyQualifiedJavaType("java.util.List")); - // 定义方法参数名(首字母小写) - String exampleParamName = lowerFirst(exampleClassName); - // 1. 添加findOne方法 Method findOneMethod = new Method("findOne"); findOneMethod.setVisibility(JavaVisibility.PUBLIC); findOneMethod.setReturnType(new FullyQualifiedJavaType(modelClassName)); - findOneMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + findOneMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); findOneMethod.addException(new FullyQualifiedJavaType("Throwable")); findOneMethod.setAbstract(true); repoInterface.addMethod(findOneMethod); @@ -167,7 +168,7 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { Method getListMethod = new Method("getList"); getListMethod.setVisibility(JavaVisibility.PUBLIC); getListMethod.setReturnType(new FullyQualifiedJavaType("List<" + modelClassName + ">")); - getListMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + getListMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); getListMethod.addException(new FullyQualifiedJavaType("Throwable")); getListMethod.setAbstract(true); repoInterface.addMethod(getListMethod); @@ -176,7 +177,7 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { Method countMethod = new Method("count"); countMethod.setVisibility(JavaVisibility.PUBLIC); countMethod.setReturnType(new FullyQualifiedJavaType("long")); - countMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + countMethod.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); countMethod.addException(new FullyQualifiedJavaType("Throwable")); countMethod.setAbstract(true); repoInterface.addMethod(countMethod); @@ -192,7 +193,9 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { String interfaceName, String modelClassName, String exampleClassName, - String mapperClassName) { + String mapperClassName, + boolean hasBLOBColumns + ) { TopLevelClass implClass = new TopLevelClass(domainRepoviewPackage + "." + implClassName); implClass.setVisibility(JavaVisibility.PUBLIC); @@ -216,7 +219,7 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { // 生成findOne方法 generateFindOneMethod(implClass, modelClassName, exampleClassName, mapperFieldName); // 生成getList方法 - generateGetListMethod(implClass, modelClassName, exampleClassName, mapperFieldName); + generateGetListMethod(implClass, modelClassName, exampleClassName, mapperFieldName, hasBLOBColumns); // 生成count方法 generateCountMethod(implClass, exampleClassName, mapperFieldName); @@ -249,15 +252,14 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { method.setVisibility(JavaVisibility.PUBLIC); method.setReturnType(new FullyQualifiedJavaType(modelClassName)); // 参数名匹配示例(首字母小写) - String exampleParamName = lowerFirst(exampleClassName); - method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); method.addException(new FullyQualifiedJavaType("Throwable")); // 方法体 - method.addBodyLine(exampleParamName + ".usePage(1, 1);"); - method.addBodyLine("List<" + modelClassName + "> dataList = getList(" + exampleParamName + ");"); - method.addBodyLine("if (dataList != null && dataList.size() > 0) {"); - method.addBodyLine(" return dataList.get(0);"); + method.addBodyLine("example.usePage(1, 1);"); + method.addBodyLine("List<" + modelClassName + "> dataList = getList(example);"); + method.addBodyLine("if (dataList != null && !dataList.isEmpty()) {"); + method.addBodyLine("return dataList.get(0);"); method.addBodyLine("}"); method.addBodyLine("return null;"); @@ -267,19 +269,22 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { /** * 生成getList方法 */ - private void generateGetListMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName) { + private void generateGetListMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName, boolean hasBLOBColumns) { Method method = new Method("getList"); method.addAnnotation("@Override"); method.setVisibility(JavaVisibility.PUBLIC); method.setReturnType(new FullyQualifiedJavaType("List<" + modelClassName + ">")); // 参数名匹配示例(首字母小写) - String exampleParamName = lowerFirst(exampleClassName); - method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); method.addException(new FullyQualifiedJavaType("Throwable")); - - // 方法体 - method.addBodyLine("return " + mapperFieldName + ".selectByExample(" + exampleParamName + ");"); - + 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);"); + } implClass.addMethod(method); } @@ -292,12 +297,11 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { method.setVisibility(JavaVisibility.PUBLIC); method.setReturnType(new FullyQualifiedJavaType("long")); // 参数名匹配示例(首字母小写) - String exampleParamName = lowerFirst(exampleClassName); - method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), exampleParamName)); + method.addParameter(new Parameter(new FullyQualifiedJavaType(exampleClassName), "example")); method.addException(new FullyQualifiedJavaType("Throwable")); // 方法体 - method.addBodyLine("return " + mapperFieldName + ".countByExample(" + exampleParamName + ");"); + method.addBodyLine("return " + mapperFieldName + ".countByExample(example);"); implClass.addMethod(method); } @@ -355,14 +359,4 @@ public class TapeRepoviewGeneratorPlugin extends PluginAdapter { return str.substring(0, 1).toLowerCase() + str.substring(1); } - /** - * 字符串首字母大写(备用) - */ - private String upperFirst(String str) { - if (str == null || str.isEmpty()) { - return str; - } - return str.substring(0, 1).toUpperCase() + str.substring(1); - } - } \ No newline at end of file diff --git a/src/main/java/com/iqudoo/framework/mybatis/abstracts/AbstractWithLimitPlugin.java b/src/main/java/com/iqudoo/framework/mybatis/abstracts/AbstractWithLimitPlugin.java deleted file mode 100644 index 6316a14..0000000 --- a/src/main/java/com/iqudoo/framework/mybatis/abstracts/AbstractWithLimitPlugin.java +++ /dev/null @@ -1,261 +0,0 @@ -package com.iqudoo.framework.mybatis.abstracts; - -import com.iqudoo.framework.mybatis.hook.ISelectSelectivePluginHook; -import com.iqudoo.framework.mybatis.utils.FormatTools; -import com.iqudoo.framework.mybatis.utils.ElementTools; -import org.mybatis.generator.api.IntrospectedTable; -import org.mybatis.generator.api.PluginAdapter; -import org.mybatis.generator.api.dom.java.*; -import org.mybatis.generator.api.dom.xml.Attribute; -import org.mybatis.generator.api.dom.xml.TextElement; -import org.mybatis.generator.api.dom.xml.XmlElement; - -import java.util.List; - -public abstract class AbstractWithLimitPlugin extends PluginAdapter implements ISelectSelectivePluginHook { - - private final static int DEFAULT_START_PAGE = 1; - private final static int DEFAULT_IGNORE_PAGE_SIZE = 10000; - private int startPage = 1; - private int ignorePageSize = DEFAULT_IGNORE_PAGE_SIZE; - - @Override - public boolean validate(List list) { - return true; - } - - @Override - public void initialized(IntrospectedTable introspectedTable) { - super.initialized(introspectedTable); - this.startPage = DEFAULT_START_PAGE; - String ignorePageSizeProperty = this.properties.getProperty("ignorePageSize"); - if (ignorePageSizeProperty != null && ignorePageSizeProperty.trim().length() > 0) { - try { - this.ignorePageSize = Integer.parseInt(ignorePageSizeProperty.trim()); - } catch (NumberFormatException ignored) { - this.ignorePageSize = DEFAULT_IGNORE_PAGE_SIZE; - } - } else { - this.ignorePageSize = DEFAULT_IGNORE_PAGE_SIZE; - } - } - - @Override - public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { - PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper(); - // 添加 minPageNum、defaultPageSize、maxPageSize、ignorePageSize 字段 - Field maxPageSizeField = ElementTools.generateField( - "maxPageSize", - JavaVisibility.PROTECTED, - integerWrapper, - "100" - ); - topLevelClass.addField(maxPageSizeField); - - Field ignorePageSizeField = ElementTools.generateField( - "ignorePageSize", - JavaVisibility.PROTECTED, - integerWrapper, - this.ignorePageSize + "" - ); - topLevelClass.addField(ignorePageSizeField); - - Field defaultPageSizeField = ElementTools.generateField( - "defaultPageSize", - JavaVisibility.PROTECTED, - integerWrapper, - "20" - ); - topLevelClass.addField(defaultPageSizeField); - - Field minPageNumField = ElementTools.generateField( - "minPageNum", - JavaVisibility.PROTECTED, - integerWrapper, - startPage + "" - ); - topLevelClass.addField(minPageNumField); - - // 添加offset和rows字段 - Field offsetField = ElementTools.generateField( - "offset", - JavaVisibility.PROTECTED, - integerWrapper, - "null" - ); - topLevelClass.addField(offsetField); - - Field rowsField = ElementTools.generateField( - "rows", - JavaVisibility.PROTECTED, - integerWrapper, - "null" - ); - topLevelClass.addField(rowsField); - - // 增加getter && setter 方法 - Method mSetMaxPageSize = ElementTools.generateSetterMethod(maxPageSizeField); - FormatTools.addMethodWithBestPosition(topLevelClass, mSetMaxPageSize); - - Method mGetMaxPageSize = ElementTools.generateGetterMethod(maxPageSizeField); - FormatTools.addMethodWithBestPosition(topLevelClass, mGetMaxPageSize); - - Method mSetIgnorePageSize = ElementTools.generateSetterMethod(ignorePageSizeField); - FormatTools.addMethodWithBestPosition(topLevelClass, mSetIgnorePageSize); - - Method mGetIgnorePageSize = ElementTools.generateGetterMethod(ignorePageSizeField); - FormatTools.addMethodWithBestPosition(topLevelClass, mGetIgnorePageSize); - - Method mSetDefaultPageSize = ElementTools.generateSetterMethod(defaultPageSizeField); - FormatTools.addMethodWithBestPosition(topLevelClass, mSetDefaultPageSize); - - Method mGetDefaultPageSize = ElementTools.generateGetterMethod(defaultPageSizeField); - FormatTools.addMethodWithBestPosition(topLevelClass, mGetDefaultPageSize); - - 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( - "limit", - JavaVisibility.PUBLIC, - topLevelClass.getType(), - new Parameter(integerWrapper, "rows") - ); - setLimit = ElementTools.generateMethodBody( - setLimit, - "this.offset = null;", - "this.rows = rows;", - "return this;" - ); - FormatTools.addMethodWithBestPosition(topLevelClass, setLimit); - - Method setLimit2 = ElementTools.generateMethod( - "limit", - JavaVisibility.PUBLIC, - topLevelClass.getType(), - new Parameter(integerWrapper, "offset"), - new Parameter(integerWrapper, "rows") - ); - setLimit2 = ElementTools.generateMethodBody( - setLimit2, - "this.offset = offset;", - "this.rows = rows;", - "return this;" - ); - FormatTools.addMethodWithBestPosition(topLevelClass, setLimit2); - - Method usePage = ElementTools.generateMethod( - "usePage", - JavaVisibility.PUBLIC, - topLevelClass.getType(), - new Parameter(integerWrapper, "pageNum"), - new Parameter(integerWrapper, "pageSize") - ); - usePage = ElementTools.generateMethodBody( - usePage, - "pageSize = pageSize == null || pageSize <= 0 ? this.defaultPageSize : pageSize;", - "pageNum = pageNum == null || pageNum < this.minPageNum ? this.minPageNum : 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.rows = cPageSize;", - "return this;" - ); - FormatTools.addMethodWithBestPosition(topLevelClass, usePage); - - // 计算获取当前页码 - Method getPageNum = ElementTools.generateMethod( - "getPageNum", - JavaVisibility.PUBLIC, - integerWrapper - ); - getPageNum = ElementTools.generateMethodBody( - getPageNum, - "if (this.rows == null || this.offset == null || this.rows == 0) {", - "return this.minPageNum;", - "}", - "return this.offset / this.rows + this.minPageNum;" - ); - FormatTools.addMethodWithBestPosition(topLevelClass, getPageNum); - // 计算获取当前每页数量 - Method getPageSize = ElementTools.generateMethod( - "getPageSize", - JavaVisibility.PUBLIC, - integerWrapper - ); - getPageSize = ElementTools.generateMethodBody( - getPageSize, - "if (this.rows == null) {", - "return this.ignorePageSize;", - "}", - "return this.rows;" - ); - FormatTools.addMethodWithBestPosition(topLevelClass, getPageSize); - - // !!! clear 方法增加 offset 和 rows的清理 - List methodList = topLevelClass.getMethods(); - for (Method method : methodList) { - if (method.getName().equals("clear")) { - method.addBodyLine("rows = null;"); - method.addBodyLine("offset = null;"); - } - } - return true; - } - - @Override - public boolean sqlMapSelectAllElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { - this.generateLimitElement(element); - return super.sqlMapSelectAllElementGenerated(element, introspectedTable); - } - - @Override - public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { - this.generateLimitElement(element); - return super.sqlMapSelectByExampleWithoutBLOBsElementGenerated(element, introspectedTable); - } - - @Override - public boolean sqlMapSelectByExampleWithBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { - this.generateLimitElement(element); - return super.sqlMapSelectByExampleWithBLOBsElementGenerated(element, introspectedTable); - } - - @Override - public void generateLimitElement(XmlElement element) { - XmlElement ifLimitNotNullElement = new XmlElement("if"); - ifLimitNotNullElement.addAttribute(new Attribute("test", "rows != null")); - // rows - XmlElement ifOffsetNotNullElement = new XmlElement("if"); - ifOffsetNotNullElement.addAttribute(new Attribute("test", "offset != null")); - ifOffsetNotNullElement.addElement(new TextElement("limit ${offset}, ${rows}")); - ifLimitNotNullElement.addElement(ifOffsetNotNullElement); - // offset - XmlElement ifOffsetNullElement = new XmlElement("if"); - ifOffsetNullElement.addAttribute(new Attribute("test", "offset == null")); - ifOffsetNullElement.addElement(new TextElement("limit ${rows}")); - ifLimitNotNullElement.addElement(ifOffsetNullElement); - element.addElement(ifLimitNotNullElement); - } - -} diff --git a/src/main/java/com/iqudoo/framework/mybatis/hook/ISelectSelectivePluginHook.java b/src/main/java/com/iqudoo/framework/mybatis/hook/ISelectSelectivePluginHook.java deleted file mode 100644 index 11da92c..0000000 --- a/src/main/java/com/iqudoo/framework/mybatis/hook/ISelectSelectivePluginHook.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.iqudoo.framework.mybatis.hook; - -import org.mybatis.generator.api.dom.xml.XmlElement; - -public interface ISelectSelectivePluginHook { - - void generateLimitElement(XmlElement element); - -} diff --git a/src/main/java/com/iqudoo/framework/mybatis/utils/ElementTools.java b/src/main/java/com/iqudoo/framework/mybatis/utils/ElementTools.java index 0b4d053..1be29dd 100644 --- a/src/main/java/com/iqudoo/framework/mybatis/utils/ElementTools.java +++ b/src/main/java/com/iqudoo/framework/mybatis/utils/ElementTools.java @@ -1,5 +1,6 @@ package com.iqudoo.framework.mybatis.utils; +import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.dom.java.*; @@ -8,6 +9,21 @@ import static org.mybatis.generator.internal.util.messages.Messages.getString; @SuppressWarnings("unused") public class ElementTools { + /** + * 检测数据表是否含有BLOB列数据 + * + * @param introspectedTable introspectedTable + * @return 是/否 + */ + public static boolean hasBLOBColumns(IntrospectedTable introspectedTable) { + for (IntrospectedColumn column : introspectedTable.getAllColumns()) { + if (column.isBLOBColumn()) { + return true; + } + } + return false; + } + /** * 生成静态常量 *