mybatis-generator擴充套件
阿新 • • 發佈:2018-11-09
在新公司的新專案想用mybatis-generator來生成DAO層,有同事提出一些改進意見,遂獲得原始碼後進行小幅改造。
目標:
- 中文註釋,精簡註釋
- Model類使用lombok簡化
- 增加selectOneByExample方法(較多的使用唯一索引查詢場景)
首先獲得原始碼
在任一專案中引入jar包,使用maven download sources獲取原始碼,最新版本1.3.7
<dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.7</version> </dependency>
構建專案
新建一個maven專案,設定groupId和artifactId
<groupId>com.mine.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.0-SNAPSHOT</version>
把解壓後的原始碼複製到目錄
在pom.xml中新增專案依賴
<dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <scope>provided</scope> <version>1.2.17</version> <optionalView Code>true</optional> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <scope>provided</scope> <version>1.7.25</version> <optional>true</optional> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <scope>provided</scope> <version>2.11.0</version> <optional>true</optional> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <scope>provided</scope> <version>1.2</version> <optional>true</optional> </dependency> <dependency> <groupId>org.apache.ant</groupId> <artifactId>ant</artifactId> <scope>provided</scope> <version>1.10.4</version> <optional>true</optional> </dependency> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <version>5.2.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.4.1</version> <scope>test</scope> </dependency> <dependency> <groupId>com.github.javaparser</groupId> <version>3.6.12</version> <artifactId>javaparser-core</artifactId> </dependency> </dependencies>
功能拓展
model中文註釋、精簡其他註釋
修改生成註釋預設用的DefaultCommentGenerator
package org.mybatis.generator.internal; import org.mybatis.generator.api.CommentGenerator; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.api.dom.java.*; import org.mybatis.generator.api.dom.xml.XmlElement; import org.mybatis.generator.internal.util.StringUtility; import java.text.SimpleDateFormat; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.Properties; import java.util.Set; /** * @author Jeff Butler */ public class DefaultCommentGenerator implements CommentGenerator { private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public DefaultCommentGenerator() { super(); } @Override public void addJavaFileComment(CompilationUnit compilationUnit) { } @Override public void addComment(XmlElement xmlElement) { } @Override public void addRootComment(XmlElement rootElement) { } @Override public void addConfigurationProperties(Properties properties) { } protected String getDateString() { return dateFormat.format(new Date()); } @Override public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) { } @Override public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) { } @Override public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { topLevelClass.addJavaDocLine("/**"); topLevelClass.addJavaDocLine(" * 生成日期:" + getDateString()); topLevelClass.addJavaDocLine(" * 表名: " + introspectedTable.getFullyQualifiedTable().toString()); topLevelClass.addJavaDocLine(" */"); } @Override public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) { } @Override public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { field.addJavaDocLine("/**"); field.addJavaDocLine(" * " + introspectedColumn.getRemarks()); field.addJavaDocLine(" */"); } @Override public void addFieldComment(Field field, IntrospectedTable introspectedTable) { } @Override public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) { } @Override public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { } @Override public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { } @Override public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> imports) { imports.add(new FullyQualifiedJavaType("javax.annotation.Generated")); String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable().toString(); method.addAnnotation(getGeneratedAnnotation(comment)); } @Override public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) { imports.add(new FullyQualifiedJavaType("javax.annotation.Generated")); String comment = "Source field: " + introspectedTable.getFullyQualifiedTable().toString() + "." + introspectedColumn.getActualColumnName(); method.addAnnotation(getGeneratedAnnotation(comment)); } @Override public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> imports) { imports.add(new FullyQualifiedJavaType("javax.annotation.Generated")); String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable().toString(); field.addAnnotation(getGeneratedAnnotation(comment)); } @Override public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) { imports.add(new FullyQualifiedJavaType("javax.annotation.Generated")); String comment = "Source field: " + introspectedTable.getFullyQualifiedTable().toString() + "." + introspectedColumn.getActualColumnName(); field.addAnnotation(getGeneratedAnnotation(comment)); String remarks = introspectedColumn.getRemarks(); if (StringUtility.stringHasValue(remarks)) { field.addJavaDocLine("/**"); field.addJavaDocLine(" * Database Column Remarks:"); String[] remarkLines = remarks.split(System.getProperty("line.separator")); for (String remarkLine : remarkLines) { field.addJavaDocLine(" * " + remarkLine); } field.addJavaDocLine(" */"); } } @Override public void addClassAnnotation(InnerClass innerClass, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> imports) { imports.add(new FullyQualifiedJavaType("javax.annotation.Generated")); String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable().toString(); innerClass.addAnnotation(getGeneratedAnnotation(comment)); } private String getGeneratedAnnotation(String comment) { StringBuilder buffer = new StringBuilder(); buffer.append("@Generated("); buffer.append("value=\""); buffer.append(MyBatisGenerator.class.getName()); buffer.append('\"'); buffer.append(", date=\""); buffer.append(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now())); buffer.append('\"'); buffer.append(", comments=\""); buffer.append(comment); buffer.append('\"'); buffer.append(')'); return buffer.toString(); } }View Code
Model類使用lombok簡化
修改BaseRecordGenerator的getCompilationUnits的方法即可
public List<CompilationUnit> getCompilationUnits() { FullyQualifiedTable table = introspectedTable.getFullyQualifiedTable(); progressCallback.startTask(getString( "Progress.8", table.toString())); //$NON-NLS-1$ Plugin plugins = context.getPlugins(); CommentGenerator commentGenerator = context.getCommentGenerator(); FullyQualifiedJavaType type = new FullyQualifiedJavaType( introspectedTable.getBaseRecordType()); TopLevelClass topLevelClass = new TopLevelClass(type); topLevelClass.addImportedType("lombok.Getter");// 匯入lombok類 topLevelClass.addImportedType("lombok.Setter"); topLevelClass.setVisibility(JavaVisibility.PUBLIC); commentGenerator.addJavaFileComment(topLevelClass); FullyQualifiedJavaType superClass = getSuperClass(); if (superClass != null) { topLevelClass.setSuperClass(superClass); topLevelClass.addImportedType(superClass); } commentGenerator.addModelClassComment(topLevelClass, introspectedTable); topLevelClass.addAnnotation("@Getter");// 增加lombok註解 topLevelClass.addAnnotation("@Setter"); List<IntrospectedColumn> introspectedColumns = getColumnsInThisClass(); if (introspectedTable.isConstructorBased()) { addParameterizedConstructor(topLevelClass, introspectedTable.getNonBLOBColumns()); if (includeBLOBColumns()) { addParameterizedConstructor(topLevelClass, introspectedTable.getAllColumns()); } if (!introspectedTable.isImmutable()) { addDefaultConstructor(topLevelClass); } } String rootClass = getRootClass(); for (IntrospectedColumn introspectedColumn : introspectedColumns) { if (RootClassInfo.getInstance(rootClass, warnings) .containsProperty(introspectedColumn)) { continue; } Field field = getJavaBeansField(introspectedColumn, context, introspectedTable); if (plugins.modelFieldGenerated(field, topLevelClass, introspectedColumn, introspectedTable, Plugin.ModelClassType.BASE_RECORD)) { topLevelClass.addField(field); topLevelClass.addImportedType(field.getType()); } } List<CompilationUnit> answer = new ArrayList<>(); if (context.getPlugins().modelBaseRecordClassGenerated( topLevelClass, introspectedTable)) { answer.add(topLevelClass); } return answer;
}
增加selectOneByExample
首先檢視類似的方法selectByExample是怎麼生成的,然後參考增加這個方法。
在IntrospectedTable中增加方法
public String getSelectOneByExampleStatementId() {
return "selectOneByExample";//可以跟其他原始碼一樣設定成常量,這裡簡單處理
}
增加一個SelectOneByExampleMethodGenerator
/** * Copyright 2006-2016 the original author or authors. * * 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 org.mybatis.generator.codegen.mybatis3.javamapper.elements; import org.mybatis.generator.api.dom.java.*; import java.util.Set; import java.util.TreeSet; /** * * @author Jeff Butler * */ public class SelectOneByExampleMethodGenerator extends AbstractJavaMapperMethodGenerator { public SelectOneByExampleMethodGenerator() { super(); } @Override public void addInterfaceElements(Interface interfaze) { Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>(); FullyQualifiedJavaType type = new FullyQualifiedJavaType( introspectedTable.getExampleType()); importedTypes.add(type); importedTypes.add(FullyQualifiedJavaType.getNewListInstance()); Method method = new Method(); method.setVisibility(JavaVisibility.PUBLIC); FullyQualifiedJavaType returnType = introspectedTable.getRules() .calculateAllFieldsClass(); method.setReturnType(returnType); method.setName(introspectedTable.getSelectOneByExampleStatementId()); method.addParameter(new Parameter(type, "example")); //$NON-NLS-1$ context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable); addMapperAnnotations(interfaze, method); if (context.getPlugins() .clientSelectByExampleWithBLOBsMethodGenerated(method, interfaze, introspectedTable)) { addExtraImports(interfaze); interfaze.addImportedTypes(importedTypes); interfaze.addMethod(method); } } public void addMapperAnnotations(Interface interfaze, Method method) { } public void addExtraImports(Interface interfaze) { } }View Code
增加一個SelectOneByExampleElementGenerator
/** * Copyright 2006-2016 the original author or authors. * * 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 org.mybatis.generator.codegen.mybatis3.xmlmapper.elements; 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 static org.mybatis.generator.internal.util.StringUtility.stringHasValue; /** * * @author Jeff Butler * */ public class SelectOneByExampleElementGenerator extends AbstractXmlElementGenerator { public SelectOneByExampleElementGenerator() { super(); } @Override public void addElements(XmlElement parentElement) { String fqjt = introspectedTable.getExampleType(); XmlElement answer = new XmlElement("select"); //$NON-NLS-1$ answer.addAttribute(new Attribute("id", //$NON-NLS-1$ introspectedTable.getSelectOneByExampleStatementId())); answer.addAttribute(new Attribute( "resultMap", introspectedTable.getBaseResultMapId())); //$NON-NLS-1$ answer.addAttribute(new Attribute("parameterType", fqjt)); //$NON-NLS-1$ context.getCommentGenerator().addComment(answer); answer.addElement(new TextElement("select")); //$NON-NLS-1$ XmlElement ifElement = new XmlElement("if"); //$NON-NLS-1$ ifElement.addAttribute(new Attribute("test", "distinct")); //$NON-NLS-1$ //$NON-NLS-2$ ifElement.addElement(new TextElement("distinct")); //$NON-NLS-1$ answer.addElement(ifElement); StringBuilder sb = new StringBuilder(); if (stringHasValue(introspectedTable .getSelectByExampleQueryId())) { sb.append('\''); sb.append(introspectedTable.getSelectByExampleQueryId()); sb.append("' as QUERYID,"); //$NON-NLS-1$ answer.addElement(new TextElement(sb.toString())); } answer.addElement(getBaseColumnListElement()); sb.setLength(0); sb.append("from "); //$NON-NLS-1$ sb.append(introspectedTable .getAliasedFullyQualifiedTableNameAtRuntime()); answer.addElement(new TextElement(sb.toString())); answer.addElement(getExampleIncludeElement()); ifElement = new XmlElement("if"); //$NON-NLS-1$ ifElement.addAttribute(new Attribute("test", "orderByClause != null")); //$NON-NLS-1$ //$NON-NLS-2$ ifElement.addElement(new TextElement("order by ${orderByClause}")); //$NON-NLS-1$ answer.addElement(ifElement); if (context.getPlugins() .sqlMapSelectByExampleWithoutBLOBsElementGenerated(answer, introspectedTable)) { parentElement.addElement(answer); } answer.addElement(new TextElement("limit 1")); } }View Code
修改JavaMapperGenerator,在getCompilationUnits方法中增加addSelectOneByExampleMethod(interfaze),這裡順帶把生成的程式碼排了個序,並且把不常用的幾個方法給註釋掉了。
@Override
public List<CompilationUnit> getCompilationUnits() {
progressCallback.startTask(getString("Progress.17", //$NON-NLS-1$
introspectedTable.getFullyQualifiedTable().toString()));
CommentGenerator commentGenerator = context.getCommentGenerator();
FullyQualifiedJavaType type = new FullyQualifiedJavaType(
introspectedTable.getMyBatis3JavaMapperType());
Interface interfaze = new Interface(type);
interfaze.setVisibility(JavaVisibility.PUBLIC);
commentGenerator.addJavaFileComment(interfaze);
String rootInterface = introspectedTable
.getTableConfigurationProperty(PropertyRegistry.ANY_ROOT_INTERFACE);
if (!stringHasValue(rootInterface)) {
rootInterface = context.getJavaClientGeneratorConfiguration()
.getProperty(PropertyRegistry.ANY_ROOT_INTERFACE);
}
if (stringHasValue(rootInterface)) {
FullyQualifiedJavaType fqjt = new FullyQualifiedJavaType(
rootInterface);
interfaze.addSuperInterface(fqjt);
interfaze.addImportedType(fqjt);
}
addInsertSelectiveMethod(interfaze);
addDeleteByPrimaryKeyMethod(interfaze);
addDeleteByExampleMethod(interfaze);
addUpdateByPrimaryKeySelectiveMethod(interfaze);
addUpdateByExampleSelectiveMethod(interfaze);
addSelectByPrimaryKeyMethod(interfaze);
addSelectOneByExampleMethod(interfaze); //由addSelectByExampleWithoutBLOBsMethod改造而來
addSelectByExampleWithoutBLOBsMethod(interfaze);
addSelectByExampleWithBLOBsMethod(interfaze);
addCountByExampleMethod(interfaze);
//addInsertMethod(interfaze);
//addUpdateByExampleWithBLOBsMethod(interfaze);
//addUpdateByExampleWithoutBLOBsMethod(interfaze);
//addUpdateByPrimaryKeyWithBLOBsMethod(interfaze);
//addUpdateByPrimaryKeyWithoutBLOBsMethod(interfaze);
List<CompilationUnit> answer = new ArrayList<>();
if (context.getPlugins().clientGenerated(interfaze, null,
introspectedTable)) {
answer.add(interfaze);
}
List<CompilationUnit> extraCompilationUnits = getExtraCompilationUnits();
if (extraCompilationUnits != null) {
answer.addAll(extraCompilationUnits);
}
return answer;
}
//增加方法
protected void addSelectOneByExampleMethod(Interface interfaze) { AbstractJavaMapperMethodGenerator methodGenerator = new SelectOneByExampleMethodGenerator(); initializeAndExecuteGenerator(methodGenerator, interfaze); }
同樣地,修改XMLMapperGenerator
protected XmlElement getSqlMapElement() { FullyQualifiedTable table = introspectedTable.getFullyQualifiedTable(); progressCallback.startTask(getString( "Progress.12", table.toString())); //$NON-NLS-1$ XmlElement answer = new XmlElement("mapper"); //$NON-NLS-1$ String namespace = introspectedTable.getMyBatis3SqlMapNamespace(); answer.addAttribute(new Attribute("namespace", //$NON-NLS-1$ namespace)); context.getCommentGenerator().addRootComment(answer); addResultMapWithoutBLOBsElement(answer); addResultMapWithBLOBsElement(answer); addExampleWhereClauseElement(answer); addMyBatis3UpdateByExampleWhereClauseElement(answer); addBaseColumnListElement(answer); addBlobColumnListElement(answer); addInsertSelectiveElement(answer); addDeleteByPrimaryKeyElement(answer); addDeleteByExampleElement(answer); addUpdateByPrimaryKeySelectiveElement(answer); addUpdateByExampleSelectiveElement(answer); addSelectByPrimaryKeyElement(answer); addSelectOneByExampleElement(answer); addSelectByExampleWithoutBLOBsElement(answer); addSelectByExampleWithBLOBsElement(answer); addCountByExampleElement(answer); //addSelectByExampleWithBLOBsElement(answer); //addInsertElement(answer); //addUpdateByExampleWithBLOBsElement(answer); //addUpdateByExampleWithoutBLOBsElement(answer); //addUpdateByPrimaryKeyWithBLOBsElement(answer); //addUpdateByPrimaryKeyWithoutBLOBsElement(answer); return answer; }
//增加方法 protected void addSelectOneByExampleElement(XmlElement parentElement) { if (introspectedTable.getRules().generateSelectByExampleWithoutBLOBs()) { AbstractXmlElementGenerator elementGenerator = new SelectOneByExampleElementGenerator(); initializeAndExecuteGenerator(elementGenerator, parentElement); } }
投入使用
deploy專案打包,然後在需要使用的專案中,修改pom.xml引入,再使用generator的generate命令即可
<plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.7</version> <dependencies> <dependency> <groupId>com.mine.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </plugin>