Compare commits

...
15 Commits
27 changed files with 1275 additions and 48 deletions
+12 -2
View File
@@ -25,6 +25,7 @@
* [乐观锁插件(OptimisticLockerPlugin)](#17-乐观锁插件)
* [表重命名配置插件(TableRenameConfigurationPlugin)](#18-表重命名配置插件)
* [Lombok插件(LombokPlugin)](#19-Lombok插件)
* [数据ModelCloneable插件(ModelCloneablePlugin)](#20-数据ModelCloneable插件)
---------------------------------------
Maven引用:
@@ -32,7 +33,7 @@ Maven引用:
<dependency>
<groupId>com.itfsw</groupId>
<artifactId>mybatis-generator-plugin</artifactId>
<version>1.2.11</version>
<version>1.2.12</version>
</dependency>
```
---------------------------------------
@@ -87,7 +88,7 @@ targetCompatibility = 1.8
def mybatisGeneratorCore = 'org.mybatis.generator:mybatis-generator-core:1.3.7'
def itfswMybatisGeneratorPlugin = 'com.itfsw:mybatis-generator-plugin:1.2.10'
def itfswMybatisGeneratorPlugin = 'com.itfsw:mybatis-generator-plugin:1.2.12'
mybatisGenerator {
verbose = false
@@ -1384,3 +1385,12 @@ public class Test {
</plugin>
</xml>
```
### 20. 数据ModelCloneable插件
数据Model实现Cloneable接口。
```xml
<xml>
<!-- 数据ModelCloneable插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.ModelCloneablePlugin"/>
</xml>
```
+3 -2
View File
@@ -3,7 +3,7 @@
<groupId>com.itfsw</groupId>
<artifactId>mybatis-generator-plugin</artifactId>
<version>1.2.12</version>
<version>1.2.14</version>
<packaging>jar</packaging>
<name>${project.groupId}:${project.artifactId}</name>
@@ -103,6 +103,7 @@
<artifactId>tools</artifactId>
<version>1.8</version>
<scope>system</scope>
<optional>true</optional>
<!-- jdk path -->
<systemPath>${env.JAVA_HOME}/lib/tools.jar</systemPath>
</dependency>
@@ -233,7 +234,7 @@
<connection>scm:git:https://github.com/itfsw/mybatis-generator-plugin.git</connection>
<developerConnection>scm:git:https://github.com/itfsw/mybatis-generator-plugin.git</developerConnection>
<url>https://github.com/itfsw/mybatis-generator-plugin</url>
<tag>V1.2.12</tag>
<tag>V1.2.14</tag>
</scm>
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++distribution++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
@@ -0,0 +1,269 @@
/*
* Copyright (c) 2018.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.itfsw.mybatis.generator.plugins;
import com.itfsw.mybatis.generator.plugins.utils.BasePlugin;
import com.itfsw.mybatis.generator.plugins.utils.FormatTools;
import com.itfsw.mybatis.generator.plugins.utils.IntrospectedTableTools;
import com.itfsw.mybatis.generator.plugins.utils.JavaElementGeneratorTools;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.internal.util.StringUtility;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* ---------------------------------------------------------------------------
* type or status enum 插件
* ---------------------------------------------------------------------------
* @author: hewei
* @time:2018/11/27 20:36
* ---------------------------------------------------------------------------
*/
public class EnumTypeStatusPlugin extends BasePlugin {
/**
* 需要生成Enum的Column
*/
public final static String PRO_ENUM_COLUMNS = "enumColumns";
public final static String REMARKS_PATTERN = ".*\\s*\\[\\s*(\\w+\\s*\\(\\s*[\\u4e00-\\u9fa5_a-zA-Z0-9]+\\s*\\)\\s*:\\s*[\\u4e00-\\u9fa5_a-zA-Z0-9]+\\s*\\,?\\s*)+\\s*\\]\\s*.*";
public final static String NEED_PATTERN = "\\[\\s*((\\w+\\s*\\(\\s*[\\u4e00-\\u9fa5_a-zA-Z0-9]+\\s*\\)\\s*:\\s*[\\u4e00-\\u9fa5_a-zA-Z0-9]+\\s*\\,?\\s*)+)\\s*\\]";
public final static String ITEM_PATTERN = "(\\w+)\\s*\\(\\s*([\\u4e00-\\u9fa5_a-zA-Z0-9]+)\\s*\\)\\s*:\\s*([\\u4e00-\\u9fa5_a-zA-Z0-9]+)";
private Map<IntrospectedColumn, List<EnumItemInfo>> enumColumns;
/**
* 具体执行顺序 http://www.mybatis.org/generator/reference/pluggingIn.html
* @param introspectedTable
*/
@Override
public void initialized(IntrospectedTable introspectedTable) {
super.initialized(introspectedTable);
this.enumColumns = new LinkedHashMap<>();
// 获取全局配置
String enumColumns = this.getProperties().getProperty(EnumTypeStatusPlugin.PRO_ENUM_COLUMNS);
// 如果有局部配置,则附加上去
String tableEnumColumns = introspectedTable.getTableConfigurationProperty(EnumTypeStatusPlugin.PRO_ENUM_COLUMNS);
if (tableEnumColumns != null) {
enumColumns = enumColumns == null ? "" : (enumColumns + ",");
enumColumns += introspectedTable.getTableConfigurationProperty(EnumTypeStatusPlugin.PRO_ENUM_COLUMNS);
}
if (StringUtility.stringHasValue(enumColumns)) {
// 切分
String[] enumColumnsStrs = enumColumns.split(",");
for (String enumColumnsStr : enumColumnsStrs) {
IntrospectedColumn column = IntrospectedTableTools.safeGetColumn(introspectedTable, enumColumnsStr);
if (column != null) {
String remarks = column.getRemarks();
String javaType = column.getFullyQualifiedJavaType().getFullyQualifiedName();
if (!StringUtility.stringHasValue(remarks) || !remarks.matches(REMARKS_PATTERN)) {
warnings.add("itfsw:插件" + EnumTypeStatusPlugin.class.getTypeName() + "没有找到column为" + enumColumnsStr.trim() + "对应格式的注释的字段!");
} else if (!(Short.class.getTypeName().equals(javaType)
|| Integer.class.getTypeName().equals(javaType)
|| Long.class.getTypeName().equals(javaType)
|| String.class.getTypeName().equals(javaType))) {
warnings.add("itfsw:插件" + EnumTypeStatusPlugin.class.getTypeName() + "找到column为" + enumColumnsStr.trim() + "对应Java类型不是Short、Integer、Long、String!");
} else {
// 提取信息
Pattern pattern = Pattern.compile(NEED_PATTERN);
Matcher matcher = pattern.matcher(remarks);
List<EnumItemInfo> itemInfos = new ArrayList<>();
if (matcher.find() && matcher.groupCount() == 2) {
String enumInfoStr = matcher.group(1);
// 根据逗号切分
String[] enumInfoStrs = enumInfoStr.split(",");
// 提取每个节点信息
for (String enumInfo : enumInfoStrs) {
pattern = Pattern.compile(ITEM_PATTERN);
matcher = pattern.matcher(enumInfo.trim());
if (matcher.find() && matcher.groupCount() == 3) {
itemInfos.add(new EnumItemInfo(column, matcher.group(1), matcher.group(3), matcher.group(2)));
}
}
}
if (itemInfos.size() > 0) {
this.enumColumns.put(column, itemInfos);
}
}
}
}
}
}
/**
* 具体执行顺序 http://www.mybatis.org/generator/reference/pluggingIn.html
* @param topLevelClass
* @param introspectedTable
* @return
*/
@Override
public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
this.generateModelEnum(topLevelClass, introspectedTable);
return super.modelPrimaryKeyClassGenerated(topLevelClass, introspectedTable);
}
/**
* 生成对应enum
* @param topLevelClass
* @param introspectedTable
*/
private void generateModelEnum(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
this.enumColumns.forEach((introspectedColumn, enumItemInfos) -> {
// 枚举跟随字段走
for (Field field : topLevelClass.getFields()) {
if (introspectedColumn.getJavaProperty().equals(field.getName())) {
String enumName = this.upperCaseFirst(field.getName());
InnerEnum innerEnum = new InnerEnum(new FullyQualifiedJavaType(enumName));
commentGenerator.addEnumComment(innerEnum, introspectedTable);
innerEnum.setVisibility(JavaVisibility.PUBLIC);
innerEnum.setStatic(true);
// 生成枚举
for (EnumItemInfo item : enumItemInfos) {
innerEnum.addEnumConstant(item.getName() + "(" + item.getValue() + ", " + item.getComment() + ")");
}
// 生成属性和构造函数
Field fValue = new Field("value", field.getType());
fValue.setVisibility(JavaVisibility.PRIVATE);
fValue.setFinal(true);
commentGenerator.addFieldComment(fValue, introspectedTable);
innerEnum.addField(fValue);
Field fName = new Field("name", FullyQualifiedJavaType.getStringInstance());
fName.setVisibility(JavaVisibility.PRIVATE);
fName.setFinal(true);
commentGenerator.addFieldComment(fName, introspectedTable);
innerEnum.addField(fName);
Method mInc = new Method(enumName);
mInc.setConstructor(true);
mInc.addBodyLine("this.value = value;");
mInc.addBodyLine("this.name = name;");
mInc.addParameter(new Parameter(fValue.getType(), "value"));
mInc.addParameter(new Parameter(fName.getType(), "name"));
commentGenerator.addGeneralMethodComment(mInc, introspectedTable);
FormatTools.addMethodWithBestPosition(innerEnum, mInc);
// 获取value的方法
Method mValue = JavaElementGeneratorTools.generateGetterMethod(fValue);
commentGenerator.addGeneralMethodComment(mValue, introspectedTable);
FormatTools.addMethodWithBestPosition(innerEnum, mValue);
Method mValue1 = JavaElementGeneratorTools.generateGetterMethod(fValue);
mValue1.setName("value");
commentGenerator.addGeneralMethodComment(mValue1, introspectedTable);
FormatTools.addMethodWithBestPosition(innerEnum, mValue1);
// 获取name的方法
Method mName = JavaElementGeneratorTools.generateGetterMethod(fName);
commentGenerator.addGeneralMethodComment(mName, introspectedTable);
FormatTools.addMethodWithBestPosition(innerEnum, mName);
topLevelClass.addInnerEnum(innerEnum);
}
}
});
}
/**
* Model 生成
* 具体执行顺序 http://www.mybatis.org/generator/reference/pluggingIn.html
* @param topLevelClass
* @param introspectedTable
* @return
*/
@Override
public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
this.generateModelEnum(topLevelClass, introspectedTable);
return super.modelBaseRecordClassGenerated(topLevelClass, introspectedTable);
}
/**
* 首字母大写
* @param s
* @return
*/
private String upperCaseFirst(String s) {
if (Character.isUpperCase(s.charAt(0))) {
return s;
} else {
return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
}
}
private class EnumItemInfo {
private IntrospectedColumn column;
private String name;
private String comment;
private String value;
public EnumItemInfo(IntrospectedColumn column, String name, String comment, String value) {
this.column = column;
this.name = name;
this.comment = comment;
this.value = value;
}
/**
* Getter method for property <tt>comment</tt>.
* @return property value of comment
* @author hewei
*/
public String getComment() {
return "\"" + comment.trim() + "\"";
}
/**
* Getter method for property <tt>name</tt>.
* @return property value of name
* @author hewei
*/
public String getName() {
return name.trim().toUpperCase();
}
/**
* Getter method for property <tt>value</tt>.
* @return property value of value
* @author hewei
*/
public String getValue() {
String javaType = this.column.getFullyQualifiedJavaType().getFullyQualifiedName();
if (Short.class.getTypeName().equals(javaType)) {
return "(short)" + value;
} else if (Long.class.getTypeName().equals(javaType)) {
return value + "L";
} else if (String.class.getTypeName().equals(javaType)) {
return "\"" + value + "\"";
}
return value;
}
}
}
@@ -10,6 +10,7 @@ import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
import org.mybatis.generator.internal.util.StringUtility;
import java.util.List;
@@ -22,9 +23,14 @@ import java.util.List;
* ---------------------------------------------------------------------------
*/
public class ExampleEnhancedPlugin extends BasePlugin {
public static final String METHOD_NEW_AND_CREATE_CRITERIA = "newAndCreateCriteria"; // newAndCreateCriteria 方法
private boolean enableColumnOperate = false; // 是否启用column的操作
// newAndCreateCriteria 方法
public static final String METHOD_NEW_AND_CREATE_CRITERIA = "newAndCreateCriteria";
// 逻辑删除列-Key
public static final String PRO_ENABLE_AND_IF = "enableAndIf";
// 是否启用column的操作
private boolean enableColumnOperate = false;
// 是否启用了过期的andIf
private boolean enableAndIf;
/**
* {@inheritDoc}
@@ -34,6 +40,8 @@ public class ExampleEnhancedPlugin extends BasePlugin {
public void initialized(IntrospectedTable introspectedTable) {
super.initialized(introspectedTable);
this.enableColumnOperate = PluginTools.checkDependencyPlugin(context, ModelColumnPlugin.class);
String enableAndIf = properties.getProperty(PRO_ENABLE_AND_IF);
this.enableAndIf = enableAndIf == null ? true : StringUtility.isTrue(enableAndIf);
}
/**
@@ -46,12 +54,17 @@ public class ExampleEnhancedPlugin extends BasePlugin {
@Override
public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
List<InnerClass> innerClasses = topLevelClass.getInnerClasses();
for (InnerClass innerClass : innerClasses) {
for (int i = 0; i < innerClasses.size(); i++) {
InnerClass innerClass = innerClasses.get(i);
if ("Criteria".equals(innerClass.getType().getShortName())) {
// 工厂方法
addFactoryMethodToCriteria(topLevelClass, innerClass, introspectedTable);
// andIf
addAndIfMethodToCriteria(topLevelClass, innerClass, introspectedTable);
if (this.enableAndIf) {
addAndIfMethodToCriteria(topLevelClass, innerClass, introspectedTable);
}
// when
addWhenToCriteria(topLevelClass, innerClass, introspectedTable);
} else if ("GeneratedCriteria".equals(innerClass.getType().getShortName())) {
// column 方法
if (this.enableColumnOperate) {
@@ -62,10 +75,12 @@ public class ExampleEnhancedPlugin extends BasePlugin {
List<Method> methods = topLevelClass.getMethods();
for (Method method : methods) {
if (!"createCriteriaInternal".equals(method.getName()))
if (!"createCriteriaInternal".equals(method.getName())) {
continue;
method.getBodyLines().set(0, "Criteria criteria = new Criteria(this);");
logger.debug("itfsw(Example增强插件):" + topLevelClass.getType().getShortName() + "修改createCriteriaInternal方法,修改构造Criteria时传入Example对象");
} else {
method.getBodyLines().set(0, "Criteria criteria = new Criteria(this);");
logger.debug("itfsw(Example增强插件):" + topLevelClass.getType().getShortName() + "修改createCriteriaInternal方法,修改构造Criteria时传入Example对象");
}
}
// orderBy方法
@@ -74,6 +89,9 @@ public class ExampleEnhancedPlugin extends BasePlugin {
// createCriteria 静态方法
this.addStaticCreateCriteriaMethodToExample(topLevelClass, introspectedTable);
// when
addWhenToExample(topLevelClass, introspectedTable);
return true;
}
@@ -215,6 +233,88 @@ public class ExampleEnhancedPlugin extends BasePlugin {
logger.debug("itfsw(Example增强插件):" + topLevelClass.getType().getShortName() + "." + innerClass.getType().getShortName() + "增加工厂方法example");
}
/**
* 增强Criteria的链式调用(when)
* @param topLevelClass
* @param innerClass
* @param introspectedTable
*/
private void addWhenToCriteria(TopLevelClass topLevelClass, InnerClass innerClass, IntrospectedTable introspectedTable) {
this.addWhenToClass(topLevelClass, innerClass, introspectedTable, "criteria");
}
/**
* 增强Example的链式调用(when)
* @param topLevelClass
* @param introspectedTable
*/
private void addWhenToExample(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
this.addWhenToClass(topLevelClass, topLevelClass, introspectedTable, "example");
}
/**
* 增强链式调用(when)
* @param topLevelClass
* @param clazz
* @param introspectedTable
*/
private void addWhenToClass(TopLevelClass topLevelClass, InnerClass clazz, IntrospectedTable introspectedTable, String type) {
// 添加接口When
InnerInterface whenInterface = new InnerInterface("I" + FormatTools.upFirstChar(type) + "When");
whenInterface.setVisibility(JavaVisibility.PUBLIC);
// ICriteriaAdd增加接口add
Method addMethod = JavaElementGeneratorTools.generateMethod(
type,
JavaVisibility.DEFAULT,
null,
new Parameter(clazz.getType(), type)
);
commentGenerator.addGeneralMethodComment(addMethod, introspectedTable);
whenInterface.addMethod(addMethod);
InnerClass innerClassWrapper = new InnerInterfaceWrapperToInnerClass(whenInterface);
// 添加注释
commentGenerator.addClassComment(innerClassWrapper, introspectedTable);
topLevelClass.addInnerClass(innerClassWrapper);
// 添加when方法
Method whenMethod = JavaElementGeneratorTools.generateMethod(
"when",
JavaVisibility.PUBLIC,
clazz.getType(),
new Parameter(FullyQualifiedJavaType.getBooleanPrimitiveInstance(), "condition"),
new Parameter(whenInterface.getType(), "then")
);
commentGenerator.addGeneralMethodComment(whenMethod, introspectedTable);
whenMethod = JavaElementGeneratorTools.generateMethodBody(
whenMethod,
"if (condition) {",
"then." + type + "(this);",
"}",
"return this;"
);
FormatTools.addMethodWithBestPosition(clazz, whenMethod);
Method whenOtherwiseMethod = JavaElementGeneratorTools.generateMethod(
"when",
JavaVisibility.PUBLIC,
clazz.getType(),
new Parameter(FullyQualifiedJavaType.getBooleanPrimitiveInstance(), "condition"),
new Parameter(whenInterface.getType(), "then"),
new Parameter(whenInterface.getType(), "otherwise")
);
commentGenerator.addGeneralMethodComment(whenOtherwiseMethod, introspectedTable);
whenOtherwiseMethod = JavaElementGeneratorTools.generateMethodBody(
whenOtherwiseMethod,
"if (condition) {",
"then." + type + "(this);",
"} else {",
"otherwise." + type + "(this);",
"}",
"return this;"
);
FormatTools.addMethodWithBestPosition(clazz, whenOtherwiseMethod);
}
/**
* 增强Criteria的链式调用,添加andIf(boolean addIf, CriteriaAdd add)方法,实现链式调用中按条件增加查询语句
@@ -222,10 +322,12 @@ public class ExampleEnhancedPlugin extends BasePlugin {
* @param innerClass
* @param introspectedTable
*/
@Deprecated
private void addAndIfMethodToCriteria(TopLevelClass topLevelClass, InnerClass innerClass, IntrospectedTable introspectedTable) {
// 添加接口CriteriaAdd
InnerInterface criteriaAddInterface = new InnerInterface("ICriteriaAdd");
criteriaAddInterface.setVisibility(JavaVisibility.PUBLIC);
criteriaAddInterface.addAnnotation("@Deprecated");
logger.debug("itfsw(Example增强插件):" + topLevelClass.getType().getShortName() + "." + innerClass.getType().getShortName() + "增加接口ICriteriaAdd");
// ICriteriaAdd增加接口add
@@ -252,6 +354,7 @@ public class ExampleEnhancedPlugin extends BasePlugin {
new Parameter(FullyQualifiedJavaType.getBooleanPrimitiveInstance(), "ifAdd"),
new Parameter(criteriaAddInterface.getType(), "add")
);
andIfMethod.addAnnotation("@Deprecated");
commentGenerator.addGeneralMethodComment(andIfMethod, introspectedTable);
andIfMethod = JavaElementGeneratorTools.generateMethodBody(
andIfMethod,
@@ -36,7 +36,7 @@ import java.util.Properties;
*/
public class ExampleTargetPlugin extends BasePlugin {
public static final String PRO_TARGET_PACKAGE = "targetPackage"; // 配置targetPackage名
private static String targetPackage; // 目标包
private String targetPackage; // 目标包
/**
* {@inheritDoc}
@@ -19,9 +19,11 @@ package com.itfsw.mybatis.generator.plugins;
import com.itfsw.mybatis.generator.plugins.utils.BasePlugin;
import com.itfsw.mybatis.generator.plugins.utils.FormatTools;
import com.itfsw.mybatis.generator.plugins.utils.JavaElementGeneratorTools;
import com.itfsw.mybatis.generator.plugins.utils.hook.ISelectSelectivePluginHook;
import org.mybatis.generator.api.IntrospectedTable;
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;
@@ -35,7 +37,7 @@ import java.util.List;
* @time:2016/12/29 18:14
* ---------------------------------------------------------------------------
*/
public class LimitPlugin extends BasePlugin {
public class LimitPlugin extends BasePlugin implements ISelectSelectivePluginHook {
/**
* {@inheritDoc}
*/
@@ -169,7 +171,7 @@ public class LimitPlugin extends BasePlugin {
*/
@Override
public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
this.generateLimitElement(element, introspectedTable);
this.generateLimitElement(element);
return true;
}
@@ -182,16 +184,23 @@ public class LimitPlugin extends BasePlugin {
*/
@Override
public boolean sqlMapSelectByExampleWithBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
this.generateLimitElement(element, introspectedTable);
this.generateLimitElement(element);
return true;
}
// ============================================ ISelectSelectivePluginHook ==========================================
@Override
public boolean sqlMapSelectByExampleSelectiveElementGenerated(Document document, XmlElement element, IntrospectedTable introspectedTable) {
this.generateLimitElementWithExample(element);
return false;
}
/**
* 生成limit节点
* @param element
* @param introspectedTable
*/
public void generateLimitElement(XmlElement element, IntrospectedTable introspectedTable) {
private void generateLimitElement(XmlElement element) {
XmlElement ifLimitNotNullElement = new XmlElement("if");
ifLimitNotNullElement.addAttribute(new Attribute("test", "rows != null"));
@@ -206,7 +215,26 @@ public class LimitPlugin extends BasePlugin {
ifLimitNotNullElement.addElement(ifOffsetNullElement);
element.addElement(ifLimitNotNullElement);
}
logger.debug("itfsw(MySQL分页插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "selectByExample方法增加分页条件。");
/**
* 生成limit节点
* @param element
*/
private void generateLimitElementWithExample(XmlElement element) {
XmlElement ifLimitNotNullElement = new XmlElement("if");
ifLimitNotNullElement.addAttribute(new Attribute("test", "example.rows != null"));
XmlElement ifOffsetNotNullElement = new XmlElement("if");
ifOffsetNotNullElement.addAttribute(new Attribute("test", "example.offset != null"));
ifOffsetNotNullElement.addElement(new TextElement("limit ${example.offset}, ${example.rows}"));
ifLimitNotNullElement.addElement(ifOffsetNotNullElement);
XmlElement ifOffsetNullElement = new XmlElement("if");
ifOffsetNullElement.addAttribute(new Attribute("test", "example.offset == null"));
ifOffsetNullElement.addElement(new TextElement("limit ${example.rows}"));
ifLimitNotNullElement.addElement(ifOffsetNullElement);
element.addElement(ifLimitNotNullElement);
}
}
@@ -331,8 +331,6 @@ public class LogicalDeletePlugin extends BasePlugin {
selectByPrimaryKey.addAttribute(new Attribute("parameterType", "map"));
context.getCommentGenerator().addComment(selectByPrimaryKey);
sb = new StringBuilder();
sb.append("select ");
@@ -18,6 +18,7 @@ package com.itfsw.mybatis.generator.plugins;
import com.itfsw.mybatis.generator.plugins.utils.*;
import com.itfsw.mybatis.generator.plugins.utils.hook.ISelectOneByExamplePluginHook;
import com.itfsw.mybatis.generator.plugins.utils.hook.ISelectSelectivePluginHook;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
@@ -180,6 +181,7 @@ public class SelectSelectivePlugin extends BasePlugin implements ISelectOneByExa
// 1. selectByExampleSelective 方法
if (this.selectByExampleSelectiveEle != null) {
FormatTools.addElementWithBestPosition(document.getRootElement(), this.selectByExampleSelectiveEle);
PluginTools.getHook(ISelectSelectivePluginHook.class).sqlMapSelectByExampleSelectiveElementGenerated(document, this.selectByExampleSelectiveEle, introspectedTable);
}
// 2. selectByPrimaryKeySelective
@@ -17,6 +17,7 @@
package com.itfsw.mybatis.generator.plugins;
import com.itfsw.mybatis.generator.plugins.utils.BasePlugin;
import com.itfsw.mybatis.generator.plugins.utils.FormatTools;
import com.itfsw.mybatis.generator.plugins.utils.IntrospectedTableTools;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.config.TableConfiguration;
@@ -88,7 +89,7 @@ public class TableRenamePlugin extends BasePlugin {
Matcher matcher = pattern.matcher(domainObjectName);
domainObjectName = matcher.replaceAll(replaceString);
// 命名规范化 首字母大写
domainObjectName = upFirstWord(domainObjectName);
domainObjectName = FormatTools.upFirstChar(domainObjectName);
try {
IntrospectedTableTools.setDomainObjectName(introspectedTable, getContext(), domainObjectName);
} catch (Exception e) {
@@ -97,13 +98,4 @@ public class TableRenamePlugin extends BasePlugin {
}
super.initialized(introspectedTable);
}
/**
* 字符串首字母大写
* @param str
* @return
*/
private String upFirstWord(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
@@ -215,7 +215,7 @@ public class FormatTools {
boolean flag = false;
while (elementIterator.hasNext()) {
Element ele = elementIterator.next();
if (ele instanceof TextElement && ((TextElement) ele).getContent().matches("<!--")) {
if (ele instanceof TextElement && ((TextElement) ele).getContent().matches(".*<!--.*")) {
flag = true;
}
@@ -223,7 +223,7 @@ public class FormatTools {
elementIterator.remove();
}
if (ele instanceof TextElement && ((TextElement) ele).getContent().matches("-->")) {
if (ele instanceof TextElement && ((TextElement) ele).getContent().matches(".*-->.*")) {
flag = false;
}
}
@@ -235,4 +235,13 @@ public class FormatTools {
element.addElement(0, tmpEle.getElements().get(i));
}
}
/**
* 首字母大写
* @param str
* @return
*/
public static String upFirstChar(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
@@ -109,7 +109,7 @@ public class JavaElementGeneratorTools {
*/
public static Method generateSetterMethod(Field field) {
Method method = generateMethod(
"set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1),
"set" + FormatTools.upFirstChar(field.getName()),
JavaVisibility.PUBLIC,
null,
new Parameter(field.getType(), field.getName())
@@ -124,7 +124,7 @@ public class JavaElementGeneratorTools {
*/
public static Method generateGetterMethod(Field field) {
Method method = generateMethod(
"get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1),
"get" + FormatTools.upFirstChar(field.getName()),
JavaVisibility.PUBLIC,
field.getType()
);
@@ -49,6 +49,7 @@ public class InnerInterface extends Interface{
* @param compilationUnit the compilation unit
* @return the formatted content
*/
@Override
public String getFormattedContent(int indentLevel, CompilationUnit compilationUnit) {
StringBuilder sb = new StringBuilder();
@@ -58,7 +59,7 @@ public class InnerInterface extends Interface{
}
if (stringHasValue(getType().getPackageName())) {
sb.append("package "); //$NON-NLS-1$
sb.append("package ");
sb.append(getType().getPackageName());
sb.append(';');
newLine(sb);
@@ -66,7 +67,7 @@ public class InnerInterface extends Interface{
}
for (String staticImport : getStaticImports()) {
sb.append("import static "); //$NON-NLS-1$
sb.append("import static ");
sb.append(staticImport);
sb.append(';');
newLine(sb);
@@ -94,19 +95,19 @@ public class InnerInterface extends Interface{
sb.append(getVisibility().getValue());
if (isFinal()) {
sb.append("final "); //$NON-NLS-1$
sb.append("final ");
}
sb.append("interface "); //$NON-NLS-1$
sb.append("interface ");
sb.append(getType().getShortName());
if (getSuperInterfaceTypes().size() > 0) {
sb.append(" extends "); //$NON-NLS-1$
sb.append(" extends ");
boolean comma = false;
for (FullyQualifiedJavaType fqjt : getSuperInterfaceTypes()) {
if (comma) {
sb.append(", "); //$NON-NLS-1$
sb.append(", ");
} else {
comma = true;
}
@@ -115,7 +116,7 @@ public class InnerInterface extends Interface{
}
}
sb.append(" {"); //$NON-NLS-1$
sb.append(" {");
indentLevel++;
Iterator<Method> mtdIter = getMethods().iterator();
@@ -50,9 +50,10 @@ public class HookAggregator implements IUpsertPluginHook,
ISelectOneByExamplePluginHook,
ITableConfigurationHook,
ILombokPluginHook,
ILogicalDeletePluginHook {
ILogicalDeletePluginHook,
ISelectSelectivePluginHook {
protected static final Logger logger = LoggerFactory.getLogger(BasePlugin.class); // 日志
protected static final Logger logger = LoggerFactory.getLogger(BasePlugin.class);
private final static HookAggregator instance = new HookAggregator();
private Context context;
@@ -343,4 +344,15 @@ public class HookAggregator implements IUpsertPluginHook,
return true;
}
// ============================================= ISelectSelectivePluginHook ==============================================
@Override
public boolean sqlMapSelectByExampleSelectiveElementGenerated(Document document, XmlElement element, IntrospectedTable introspectedTable) {
for (ISelectSelectivePluginHook plugin : this.getPlugins(ISelectSelectivePluginHook.class)) {
if (!plugin.sqlMapSelectByExampleSelectiveElementGenerated(document, element, introspectedTable)) {
return false;
}
}
return true;
}
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.itfsw.mybatis.generator.plugins.utils.hook;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.XmlElement;
/**
* ---------------------------------------------------------------------------
*
* ---------------------------------------------------------------------------
* @author: hewei
* @time:2018/12/18 14:57
* ---------------------------------------------------------------------------
*/
public interface ISelectSelectivePluginHook {
boolean sqlMapSelectByExampleSelectiveElementGenerated(Document document, XmlElement element, IntrospectedTable introspectedTable);
}
@@ -20,6 +20,8 @@ import com.itfsw.mybatis.generator.plugins.tools.*;
import org.apache.ibatis.session.SqlSession;
import org.junit.Assert;
import org.junit.Test;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.MyBatisGenerator;
import java.lang.reflect.Array;
import java.util.List;
@@ -142,4 +144,20 @@ public class BugFixedTest {
}
});
}
/**
* 表重命名配置插件生成的大小写错误
* @throws Exception
*/
@Test
public void issues63() throws Exception {
MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/BugFixedTest/issues-63.xml");
MyBatisGenerator generator = tool.generate(() -> DBHelper.createDB("scripts/BugFixedTest/issues-63.sql"));
for (GeneratedJavaFile file : generator.getGeneratedJavaFiles()) {
String fileName = file.getFileName();
if (fileName.startsWith("Repaydetail")){
Assert.assertTrue("官方自己的问题", true);
}
}
}
}
@@ -0,0 +1,122 @@
/*
* Copyright (c) 2018.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.itfsw.mybatis.generator.plugins;
import com.itfsw.mybatis.generator.plugins.tools.AbstractShellCallback;
import com.itfsw.mybatis.generator.plugins.tools.DBHelper;
import com.itfsw.mybatis.generator.plugins.tools.MyBatisGeneratorTool;
import com.itfsw.mybatis.generator.plugins.tools.ObjectUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException;
import java.sql.SQLException;
/**
* ---------------------------------------------------------------------------
*
* ---------------------------------------------------------------------------
* @author: hewei
* @time:2018/11/27 21:03
* ---------------------------------------------------------------------------
*/
public class EnumTypeStatusPluginTest {
/**
* 初始化数据库
*/
@BeforeClass
public static void init() throws SQLException, IOException {
DBHelper.createDB("scripts/EnumTypeStatusPlugin/init.sql");
}
/**
* 测试配置异常
*/
@Test
public void testWarnings() throws Exception {
// 1. 注释格式不对
MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/EnumTypeStatusPlugin/mybatis-generator-with-wrong-comment.xml");
tool.generate();
Assert.assertEquals(tool.getWarnings().get(0), "itfsw:插件" + EnumTypeStatusPlugin.class.getTypeName() + "没有找到column为field2对应格式的注释的字段!");
// 2. 不支持的类型
tool = MyBatisGeneratorTool.create("scripts/EnumTypeStatusPlugin/mybatis-generator-with-unsupport-type.xml");
tool.generate();
Assert.assertEquals(tool.getWarnings().get(0), "itfsw:插件" + EnumTypeStatusPlugin.class.getTypeName() + "找到column为field2对应Java类型不是Short、Integer、Long、String!");
}
/**
* 测试生成的enum
* @throws Exception
*/
@Test
public void testEnum() throws Exception{
MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/EnumTypeStatusPlugin/mybatis-generator.xml");
tool.generate(new AbstractShellCallback() {
@Override
public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception {
// 1. 测试标准注释
ObjectUtil enumField2Success = new ObjectUtil(loader, packagz + ".Tb$Field2#SUCCESS");
Assert.assertEquals(enumField2Success.invoke("value"), (short)0);
Assert.assertEquals(enumField2Success.invoke("getValue"), (short)0);
Assert.assertEquals(enumField2Success.invoke("getName"), "禁用");
ObjectUtil enumField2FailType = new ObjectUtil(loader, packagz + ".Tb$Field2#FAIL_TYPE");
Assert.assertEquals(enumField2FailType.invoke("value"), (short)1);
Assert.assertEquals(enumField2FailType.invoke("getValue"), (short)1);
Assert.assertEquals(enumField2FailType.invoke("getName"), "启用");
// 2. 字符串类型的
ObjectUtil enumField3StrSuccess = new ObjectUtil(loader, packagz + ".Tb$Field3Str#SUCCESS");
Assert.assertEquals(enumField3StrSuccess.invoke("value"), "成都");
Assert.assertEquals(enumField3StrSuccess.invoke("getValue"), "成都");
Assert.assertEquals(enumField3StrSuccess.invoke("getName"), "禁用");
// 3. 全局支持
ObjectUtil enumStatusSuccess = new ObjectUtil(loader, packagz + ".Tb$Status#SUCCESS");
Assert.assertEquals(enumStatusSuccess.invoke("value"), (short)0);
Assert.assertEquals(enumStatusSuccess.invoke("getValue"), (short)0);
Assert.assertEquals(enumStatusSuccess.invoke("getName"), "禁用");
// 4. 特殊格式的注释
ObjectUtil enumTypeSuccess = new ObjectUtil(loader, packagz + ".Tb$Type#SUCCESS");
Assert.assertEquals(enumTypeSuccess.invoke("value"), 0L);
Assert.assertEquals(enumTypeSuccess.invoke("getValue"), 0L);
Assert.assertEquals(enumTypeSuccess.invoke("getName"), "禁用");
ObjectUtil enumTypeFailType = new ObjectUtil(loader, packagz + ".Tb$Type#FAIL_TYPE");
Assert.assertEquals(enumTypeFailType.invoke("value"), 1L);
Assert.assertEquals(enumTypeFailType.invoke("getValue"), 1L);
Assert.assertEquals(enumTypeFailType.invoke("getName"), "启用");
// 5. 有换行的
ObjectUtil enumBreakLineSuccess = new ObjectUtil(loader, packagz + ".Tb$BreakLine#SUCCESS");
Assert.assertEquals(enumBreakLineSuccess.invoke("value"), 0L);
Assert.assertEquals(enumBreakLineSuccess.invoke("getValue"), 0L);
Assert.assertEquals(enumBreakLineSuccess.invoke("getName"), "禁用");
ObjectUtil enumBreakLineFailType = new ObjectUtil(loader, packagz + ".Tb$BreakLine#FAIL_TYPE");
Assert.assertEquals(enumBreakLineFailType.invoke("value"), 1L);
Assert.assertEquals(enumBreakLineFailType.invoke("getValue"), 1L);
Assert.assertEquals(enumBreakLineFailType.invoke("getName"), "启用");
}
});
}
}
@@ -93,7 +93,7 @@ public class ExampleEnhancedPluginTest {
* @throws Exception
*/
@Test
public void testStaticCreateCriteria() throws Exception{
public void testStaticCreateCriteria() throws Exception {
MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/ExampleEnhancedPlugin/mybatis-generator.xml");
tool.generate(new AbstractShellCallback() {
@Override
@@ -148,6 +148,161 @@ public class ExampleEnhancedPluginTest {
});
}
/**
* 测试when方法
*/
@Test
public void testWhen() throws Exception {
MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/ExampleEnhancedPlugin/mybatis-generator.xml");
// Criteria When
tool.generate(new AbstractShellCallback() {
@Override
public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception {
ObjectUtil tbMapper = new ObjectUtil(sqlSession.getMapper(loader.loadClass(packagz + ".TbMapper")));
// =============================== Criteria When ======================================
// 1. when true
ObjectUtil tbExample = new ObjectUtil(loader, packagz + ".TbExample");
ObjectUtil tbExampleCriteria = new ObjectUtil(tbExample.invoke("createCriteria"));
// 代理实现接口
Object criteriaThen = Proxy.newProxyInstance(loader, new Class[]{
loader.loadClass(packagz + ".TbExample$ICriteriaWhen")
}, new TestCriteriaWhenInvocationHandler(0));
// 找到只有两个参数的when
List<Method> methods = tbExampleCriteria.getMethods("when");
Method method = null;
for (Method m : methods) {
if (m.getParameters().length == 2) {
method = m;
}
}
method.invoke(tbExampleCriteria.getObject(), true, criteriaThen);
String sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "selectByExample", tbExample.getObject());
Assert.assertEquals(sql, "select id, field1, field2 from tb WHERE ( id = '5' )");
// 2. when false
ObjectUtil tbExample1 = new ObjectUtil(loader, packagz + ".TbExample");
ObjectUtil tbExampleCriteria1 = new ObjectUtil(tbExample1.invoke("createCriteria"));
// 找到只有两个参数的when
methods = tbExampleCriteria1.getMethods("when");
for (Method m : methods) {
if (m.getParameters().length == 2) {
method = m;
}
}
method.invoke(tbExampleCriteria1.getObject(), false, criteriaThen);
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "selectByExample", tbExample1.getObject());
Assert.assertEquals(sql, "select id, field1, field2 from tb");
// 3. otherwise
Object criteriaOtherwise = Proxy.newProxyInstance(loader, new Class[]{
loader.loadClass(packagz + ".TbExample$ICriteriaWhen")
}, new TestCriteriaWhenInvocationHandler(1));
ObjectUtil tbExample2 = new ObjectUtil(loader, packagz + ".TbExample");
ObjectUtil tbExampleCriteria2 = new ObjectUtil(tbExample2.invoke("createCriteria"));
// 找到只有三个参数的when
methods = tbExampleCriteria2.getMethods("when");
for (Method m : methods) {
if (m.getParameters().length == 3) {
method = m;
}
}
method.invoke(tbExampleCriteria2.getObject(), true, criteriaThen, criteriaOtherwise);
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "selectByExample", tbExample2.getObject());
Assert.assertEquals(sql, "select id, field1, field2 from tb WHERE ( id = '5' )");
ObjectUtil tbExample3 = new ObjectUtil(loader, packagz + ".TbExample");
ObjectUtil tbExampleCriteria3 = new ObjectUtil(tbExample3.invoke("createCriteria"));
// 找到只有三个参数的when
methods = tbExampleCriteria3.getMethods("when");
for (Method m : methods) {
if (m.getParameters().length == 3) {
method = m;
}
}
method.invoke(tbExampleCriteria3.getObject(), false, criteriaThen, criteriaOtherwise);
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "selectByExample", tbExample3.getObject());
Assert.assertEquals(sql, "select id, field1, field2 from tb WHERE ( id = '10' )");
// =============================== Example When ======================================
// 1. when true
ObjectUtil tbExample4 = new ObjectUtil(loader, packagz + ".TbExample");
// 代理实现接口
Object exampleThen = Proxy.newProxyInstance(loader, new Class[]{
loader.loadClass(packagz + ".TbExample$IExampleWhen")
}, new TestExampleWhenInvocationHandler(0));
// 找到只有两个参数的when
methods = tbExample4.getMethods("when");
for (Method m : methods) {
if (m.getParameters().length == 2) {
method = m;
}
}
method.invoke(tbExample4.getObject(), true, exampleThen);
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "selectByExample", tbExample4.getObject());
Assert.assertEquals(sql, "select id, field1, field2 from tb WHERE ( field1 = 'f3' )");
// 2. when false
ObjectUtil tbExample5 = new ObjectUtil(loader, packagz + ".TbExample");
// 找到只有两个参数的when
methods = tbExample5.getMethods("when");
for (Method m : methods) {
if (m.getParameters().length == 2) {
method = m;
}
}
method.invoke(tbExample5.getObject(), false, exampleThen);
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "selectByExample", tbExample5.getObject());
Assert.assertEquals(sql, "select id, field1, field2 from tb");
// 3. otherwise
Object exampleOtherwise = Proxy.newProxyInstance(loader, new Class[]{
loader.loadClass(packagz + ".TbExample$IExampleWhen")
}, new TestExampleWhenInvocationHandler(1));
ObjectUtil tbExample6 = new ObjectUtil(loader, packagz + ".TbExample");
// 找到只有三个参数的when
methods = tbExample6.getMethods("when");
for (Method m : methods) {
if (m.getParameters().length == 3) {
method = m;
}
}
method.invoke(tbExample6.getObject(), true, exampleThen, exampleOtherwise);
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "selectByExample", tbExample6.getObject());
Assert.assertEquals(sql, "select id, field1, field2 from tb WHERE ( field1 = 'f3' )");
ObjectUtil tbExample7 = new ObjectUtil(loader, packagz + ".TbExample");
// 找到只有三个参数的when
methods = tbExample7.getMethods("when");
for (Method m : methods) {
if (m.getParameters().length == 3) {
method = m;
}
}
method.invoke(tbExample7.getObject(), false, exampleThen, exampleOtherwise);
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "selectByExample", tbExample7.getObject());
Assert.assertEquals(sql, "select id, field1, field2 from tb WHERE ( field1 = 'f2' )");
}
});
}
/**
* 测试配置ModelColumnPlugin插件
*/
@@ -238,4 +393,57 @@ public class ExampleEnhancedPluginTest {
return null;
}
}
/**
* 代理实现
*/
private class TestCriteriaWhenInvocationHandler implements InvocationHandler {
private Integer type;
public TestCriteriaWhenInvocationHandler(Integer type) {
this.type = type;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("criteria")) {
ObjectUtil tbExampleCriteria = new ObjectUtil(args[0]);
if (type == 0) {
tbExampleCriteria.invoke("andIdEqualTo", 5l);
} else {
tbExampleCriteria.invoke("andIdEqualTo", 10l);
}
return tbExampleCriteria.getObject();
}
return null;
}
}
/**
* 代理实现
*/
private class TestExampleWhenInvocationHandler implements InvocationHandler {
private Integer type;
public TestExampleWhenInvocationHandler(Integer type) {
this.type = type;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("example")) {
ObjectUtil tbExample = new ObjectUtil(args[0]);
// !!!! 不要使用orderBy 动态代理后对于可变参数判断有问题
if (type == 0) {
ObjectUtil criteria = new ObjectUtil(tbExample.invoke("or"));
criteria.invoke("andField1EqualTo", "f3");
} else {
ObjectUtil criteria = new ObjectUtil(tbExample.invoke("or"));
criteria.invoke("andField1EqualTo", "f2");
}
return tbExample.getObject();
}
return null;
}
}
}
@@ -25,6 +25,7 @@ import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import java.io.IOException;
import java.lang.reflect.Array;
import java.sql.SQLException;
import java.util.List;
@@ -95,4 +96,39 @@ public class LimitPluginTest {
}
});
}
/**
* 整合SelectSelectivePlugin
* @throws Exception
*/
@Test
public void testWithSelectSelectivePlugin() throws Exception {
MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/LimitPlugin/mybatis-generator-with-SelectSelectivePlugin.xml");
tool.generate(new AbstractShellCallback() {
@Override
public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception {
// 1. 测试limit 方法
ObjectUtil tbMapper = new ObjectUtil(sqlSession.getMapper(loader.loadClass(packagz + ".TbMapper")));
ObjectUtil tbExample = new ObjectUtil(loader, packagz + ".TbExample");
tbExample.invoke("limit", 5);
ObjectUtil columnField1 = new ObjectUtil(loader, packagz + ".Tb$Column#field1");
// java 动态参数不能有两个会冲突,最后一个封装成Array!!!必须使用反射创建指定类型数组,不然调用invoke对了可变参数会检查类型!
Object columns = Array.newInstance(columnField1.getCls(), 1);
Array.set(columns, 0, columnField1.getObject());
// 调用limit(5)方法
String sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "selectByExampleSelective", tbExample.getObject(), columns);
Assert.assertEquals(sql, "select field1 from tb limit 5");
// 调用limit(1, 5)方法
tbExample.invoke("limit", 1, 5);
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "selectByExampleSelective", tbExample.getObject(), columns);
Assert.assertEquals(sql, "select field1 from tb limit 1, 5");
// 执行一次看结果
List list = (List) tbMapper.invoke("selectByExampleSelective", tbExample.getObject(), columns);
Assert.assertEquals(list.size(), 5);
}
});
}
}
@@ -110,6 +110,21 @@ public class MyBatisGeneratorTool {
}, callback);
}
/**
* 执行MyBatisGenerator
* @param before
* @return
* @throws SQLException
* @throws IOException
* @throws InterruptedException
*/
public MyBatisGenerator generate(IBeforeCallback before) throws Exception {
before.run();
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, new DefaultShellCallback(true), warnings);
myBatisGenerator.generate(null, null, null, false);
return myBatisGenerator;
}
/**
* 执行MyBatisGenerator(不生成文件)
* @return
@@ -40,7 +40,7 @@ public class ObjectUtil {
* @param loader
* @param cls
*/
public ObjectUtil(ClassLoader loader, String cls) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
public ObjectUtil(ClassLoader loader, String cls) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
if (cls.indexOf("#") == -1) {
this.cls = loader.loadClass(cls);
this.object = this.cls.newInstance();
@@ -51,12 +51,11 @@ public class ObjectUtil {
Object[] constants = this.cls.getEnumConstants();
for (Object object : constants) {
ObjectUtil eObject = new ObjectUtil(object);
if (strs[1].equals(eObject.get("name"))) {
if (strs[1].equals(eObject.invoke("name"))) {
this.object = object;
break;
}
}
System.out.println("");
} else {
throw new ClassNotFoundException("没有找到对应枚举" + strs[0]);
}
@@ -0,0 +1,27 @@
/*
Navicat MySQL Data Transfer
Source Server : localhost
Source Server Version : 50617
Source Host : localhost:3306
Source Database : mybatis-generator-plugin
Target Server Type : MYSQL
Target Server Version : 50617
File Encoding : 65001
Date: 2017-06-27 11:17:08
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for tb
-- ----------------------------
DROP TABLE IF EXISTS `t_repay_detail`;
CREATE TABLE `t_repay_detail` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '注释1',
`field1` varchar(255) DEFAULT NULL COMMENT '注释2',
`vs` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2018.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="db.properties"/>
<!--导入属性配置 -->
<context id="default" targetRuntime="MyBatis3">
<property name="autoDelimitKeywords" value="true"/>
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 乐观锁插件 -->
<!--jdbc的数据库连接 -->
<jdbcConnection driverClass="${driver}" connectionURL="${url}" userId="${username}" password="${password}" />
<!-- Model模型生成器,用来生成含有主键key的类,记录类 以及查询Example类
targetPackage 指定生成的model生成所在的包名
targetProject 指定在该项目下所在的路径 -->
<javaModelGenerator targetPackage="" targetProject="">
<!-- 是否对model添加 构造函数 -->
<property name="constructorBased" value="true"/>
<!-- 给Model添加一个父类 -->
<!--<property name="rootClass" value="com.itfsw.base"/>-->
</javaModelGenerator>
<!--Mapper映射文件生成所在的目录 为每一个数据库的表生成对应的SqlMap文件 -->
<sqlMapGenerator targetPackage="" targetProject="" />
<!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口 -->
<javaClientGenerator targetPackage="" targetProject="" type="XMLMAPPER"/>
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 要自动生成的表 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<table tableName="t_repay_detail">
<domainObjectRenamingRule searchString="^T" replaceString="" />
</table>
</context>
</generatorConfiguration>
@@ -0,0 +1,64 @@
/*
Navicat MySQL Data Transfer
Source Server : localhost
Source Server Version : 50617
Source Host : localhost:3306
Source Database : mybatis-generator-plugin
Target Server Type : MYSQL
Target Server Version : 50617
File Encoding : 65001
Date: 2017-06-26 17:30:13
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for tb
-- ----------------------------
DROP TABLE IF EXISTS `tb`;
CREATE TABLE `tb` (
`field1` varchar(255) DEFAULT NULL COMMENT '注释2',
`field2` smallint(3) COMMENT '注释[success(0):禁用, fail_type(1):启用]',
`field3_str` varchar(255) COMMENT '注释111[success(成都):禁用, type(成都11):启用]',
`status` smallint(3) COMMENT '注释[success(0):禁用, fail(1):启用]',
`type` bigint(20) COMMENT '注释 [ success ( 0 ) : 禁用 , fail_type ( 1 ) : 启用 ] 阿斯顿覅就就',
`break_line` bigint(20) COMMENT '换行的注释
[
success ( 0 ) : 禁用 ,
fail_type ( 1 ) : 启用
]
发士大夫撒旦法'
);
-- ----------------------------
-- Records of tb
-- ----------------------------
-- ----------------------------
-- Table structure for tb_unsupport_type
-- ----------------------------
DROP TABLE IF EXISTS `tb_unsupport_type`;
CREATE TABLE `tb_unsupport_type` (
`field1` varchar(255) DEFAULT NULL COMMENT '注释2',
`field2` blob COMMENT '注释[success(0):禁用, fail_type(1):启用]发士大夫大事发生的'
);
-- ----------------------------
-- Records of tb_unsupport_type
-- ----------------------------
-- ----------------------------
-- Table structure for tb_wrong_comment
-- ----------------------------
DROP TABLE IF EXISTS `tb_wrong_comment`;
CREATE TABLE `tb_wrong_comment` (
`field1` varchar(255) DEFAULT NULL COMMENT '注释2',
`field2` smallint(3) COMMENT '注释success(0):禁用, fail_type(1):启用]发士大夫大事发生的'
);
-- ----------------------------
-- Records of tb_wrong_comment
-- ----------------------------
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2018.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="db.properties"/>
<!--导入属性配置 -->
<context id="default" targetRuntime="MyBatis3">
<!-- 插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.EnumTypeStatusPlugin"/>
<commentGenerator>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!--jdbc的数据库连接 -->
<jdbcConnection driverClass="${driver}" connectionURL="${url}" userId="${username}" password="${password}" />
<!-- Model模型生成器,用来生成含有主键key的类,记录类 以及查询Example类
targetPackage 指定生成的model生成所在的包名
targetProject 指定在该项目下所在的路径 -->
<javaModelGenerator targetPackage="" targetProject="">
<!-- 是否对model添加 构造函数 -->
<property name="constructorBased" value="true"/>
<!-- 给Model添加一个父类 -->
<!--<property name="rootClass" value="com.itfsw.base"/>-->
</javaModelGenerator>
<!--Mapper映射文件生成所在的目录 为每一个数据库的表生成对应的SqlMap文件 -->
<sqlMapGenerator targetPackage="" targetProject="" />
<!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口 -->
<javaClientGenerator targetPackage="" targetProject="" type="XMLMAPPER"/>
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 要自动生成的表 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<table tableName="tb_unsupport_type">
<property name="enumColumns" value="field2"/>
</table>
</context>
</generatorConfiguration>
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2018.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="db.properties"/>
<!--导入属性配置 -->
<context id="default" targetRuntime="MyBatis3">
<!-- 插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.EnumTypeStatusPlugin"/>
<commentGenerator>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!--jdbc的数据库连接 -->
<jdbcConnection driverClass="${driver}" connectionURL="${url}" userId="${username}" password="${password}" />
<!-- Model模型生成器,用来生成含有主键key的类,记录类 以及查询Example类
targetPackage 指定生成的model生成所在的包名
targetProject 指定在该项目下所在的路径 -->
<javaModelGenerator targetPackage="" targetProject="">
<!-- 是否对model添加 构造函数 -->
<property name="constructorBased" value="true"/>
<!-- 给Model添加一个父类 -->
<!--<property name="rootClass" value="com.itfsw.base"/>-->
</javaModelGenerator>
<!--Mapper映射文件生成所在的目录 为每一个数据库的表生成对应的SqlMap文件 -->
<sqlMapGenerator targetPackage="" targetProject="" />
<!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口 -->
<javaClientGenerator targetPackage="" targetProject="" type="XMLMAPPER"/>
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 要自动生成的表 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<table tableName="tb_wrong_comment">
<property name="enumColumns" value="field2"/>
</table>
</context>
</generatorConfiguration>
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2018.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="db.properties"/>
<!--导入属性配置 -->
<context id="default" targetRuntime="MyBatis3">
<!-- 插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.EnumTypeStatusPlugin">
<property name="enumColumns" value="type, status"/>
</plugin>
<commentGenerator>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!--jdbc的数据库连接 -->
<jdbcConnection driverClass="${driver}" connectionURL="${url}" userId="${username}" password="${password}" />
<!-- Model模型生成器,用来生成含有主键key的类,记录类 以及查询Example类
targetPackage 指定生成的model生成所在的包名
targetProject 指定在该项目下所在的路径 -->
<javaModelGenerator targetPackage="" targetProject="">
<!-- 是否对model添加 构造函数 -->
<property name="constructorBased" value="true"/>
<!-- 给Model添加一个父类 -->
<!--<property name="rootClass" value="com.itfsw.base"/>-->
</javaModelGenerator>
<!--Mapper映射文件生成所在的目录 为每一个数据库的表生成对应的SqlMap文件 -->
<sqlMapGenerator targetPackage="" targetProject="" />
<!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口 -->
<javaClientGenerator targetPackage="" targetProject="" type="XMLMAPPER"/>
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 要自动生成的表 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<table tableName="tb">
<property name="enumColumns" value="field2, field3_str, break_line"/>
</table>
</context>
</generatorConfiguration>
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2018.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="db.properties"/>
<!--导入属性配置 -->
<context id="default" targetRuntime="MyBatis3">
<!-- 插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.LimitPlugin"/>
<plugin type="com.itfsw.mybatis.generator.plugins.SelectSelectivePlugin"/>
<plugin type="com.itfsw.mybatis.generator.plugins.ModelColumnPlugin"/>
<!--jdbc的数据库连接 -->
<jdbcConnection driverClass="${driver}" connectionURL="${url}" userId="${username}" password="${password}" />
<!-- Model模型生成器,用来生成含有主键key的类,记录类 以及查询Example类
targetPackage 指定生成的model生成所在的包名
targetProject 指定在该项目下所在的路径 -->
<javaModelGenerator targetPackage="" targetProject="">
<!-- 是否对model添加 构造函数 -->
<property name="constructorBased" value="true"/>
<!-- 给Model添加一个父类 -->
<!--<property name="rootClass" value="com.itfsw.base"/>-->
</javaModelGenerator>
<!--Mapper映射文件生成所在的目录 为每一个数据库的表生成对应的SqlMap文件 -->
<sqlMapGenerator targetPackage="" targetProject="" />
<!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口 -->
<javaClientGenerator targetPackage="" targetProject="" type="XMLMAPPER"/>
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 要自动生成的表 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<table tableName="tb">
<generatedKey column="id" sqlStatement="MySql" identity="true"/>
</table>
</context>
</generatorConfiguration>