用 IEDA 的 New Project 创建一个新的空的 Maven 类型的项目 JDK 选择 11

    下面是添加依赖和相关设置的完整的 pom.xml (在Mac OS下)

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0</modelVersion>
    6. <groupId>com.longser.mybatis</groupId>
    7. <artifactId>generatorr</artifactId>
    8. <version>1.0</version>
    9. <properties>
    10. <java.version>1.11</java.version>
    11. </properties>
    12. <dependencies>
    13. <dependency>
    14. <groupId>org.mybatis.generator</groupId>
    15. <artifactId>mybatis-generator-core</artifactId>
    16. <version>1.4.0</version>
    17. </dependency>
    18. </dependencies>
    19. <build>
    20. <pluginManagement>
    21. <plugins>
    22. <plugin>
    23. <groupId>org.apache.maven.plugins</groupId>
    24. <artifactId>maven-compiler-plugin</artifactId>
    25. <configuration>
    26. <source>11</source>
    27. <target>11</target>
    28. </configuration>
    29. </plugin>
    30. <plugin>
    31. <groupId>org.apache.maven.plugins</groupId>
    32. <artifactId>maven-deploy-plugin</artifactId>
    33. <version>3.0.0-M1</version>
    34. </plugin>
    35. </plugins>
    36. </pluginManagement>
    37. </build>
    38. <distributionManagement>
    39. <repository>
    40. <id>localRepository</id>
    41. <url>file:~/.m2/Repository</url>
    42. </repository>
    43. </distributionManagement>
    44. </project>

    下面是注释生成器和插件的代码

    package com.longser.mybatis.generator;
    
    import static org.mybatis.generator.internal.util.StringUtility.isTrue;
    
    import java.text.SimpleDateFormat;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Date;
    import java.util.List;
    import java.util.Optional;
    import java.util.Properties;
    import java.util.Set;
    
    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.CompilationUnit;
    import org.mybatis.generator.api.dom.java.Field;
    import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
    import org.mybatis.generator.api.dom.java.InnerClass;
    import org.mybatis.generator.api.dom.java.InnerEnum;
    import org.mybatis.generator.api.dom.java.JavaElement;
    import org.mybatis.generator.api.dom.java.Method;
    import org.mybatis.generator.api.dom.java.Parameter;
    import org.mybatis.generator.api.dom.java.TopLevelClass;
    import org.mybatis.generator.api.dom.kotlin.KotlinFile;
    import org.mybatis.generator.api.dom.xml.TextElement;
    import org.mybatis.generator.api.dom.xml.XmlElement;
    import org.mybatis.generator.config.MergeConstants;
    import org.mybatis.generator.config.PropertyRegistry;
    import org.mybatis.generator.internal.util.StringUtility;
    
    /**
     *
     * <p>自定义的MyBatis Generator注释生成器</p>
     * <p>内容是在官方代码基础上修改的</p>
     *
     * @see org.mybatis.generator.api.CommentGenerator
     * @see org.mybatis.generator.internal.DefaultCommentGenerator
     * @see "https://github.com/mybatis/generator/blob/master/core/mybatis-generator-core/src/main/java/org/mybatis/generator/internal/DefaultCommentGenerator.java"
     *
     * @author David
     * @version 1.0.0
     * @since 2021年6月11日
     */
    @SuppressWarnings("unused")
    public class MyCommentGenerator implements CommentGenerator {
    
        private final Properties properties;
    
        /**
         * 抑制日期  默认false:不抑制
         */
        private boolean suppressDate;
        /**
         * 抑制注释 默认false:不抑制
         */
        private boolean suppressAllComments;
    
        /**
         * 显示数据库comments 默认false:不显示
         * 如果suppressAllComments是true, 这个选项被忽略
         */
        private boolean addRemarkComments;
        /**
         * 日期格式
         */
        private SimpleDateFormat dateFormat;
    
        /**
         * 当前用户的名字
         */
        private final String userName;
    
        public MyCommentGenerator() {
            super();
            properties = new Properties();
            suppressDate = false;
            suppressAllComments = false;
            addRemarkComments = false;
            userName = System.getProperty("user.name");
        }
    
        @Override
        public void addJavaFileComment(CompilationUnit compilationUnit) {
            // add no file level comments by default
        }
    
        /**
         * @param xmlElement the xml element
         */
        @Override
        public void addComment(XmlElement xmlElement) {
            if (suppressAllComments) {
                return;
            }
    
            xmlElement.addElement(new TextElement("<!-- " + MergeConstants.NEW_ELEMENT_TAG + " -->"));
    
        }
    
        @Override
        public void addRootComment(XmlElement rootElement) {
            // add no document level comments by default
        }
    
        /**
         * 读取配置文件
         */
        @Override
        public void addConfigurationProperties(Properties properties) {
            this.properties.putAll(properties);
    
            suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE));
    
            suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));
    
            addRemarkComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_ADD_REMARK_COMMENTS));
    
            String dateFormatString = properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_DATE_FORMAT);
            if (StringUtility.stringHasValue(dateFormatString)) {
                dateFormat = new SimpleDateFormat(dateFormatString);
            }
        }
    
        /**
         * This method adds the custom javadoc tag for. You may do nothing if you do not
         * wish to include the Javadoc tag - however, if you do not include the Javadoc
         * tag then the Java merge capability of the eclipse plugin will break.
         *
         * @param javaElement       the java element
         * @param markAsDoNotDelete the mark as do not delete
         */
        protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) {
            javaElement.addJavaDocLine(" *");
            String sb = " * " +
                    MergeConstants.NEW_ELEMENT_TAG;
            javaElement.addJavaDocLine(sb);
        }
    
        /**
         * Returns a formated date string to include in the Javadoc tag and XML
         * comments. You may return null if you do not want the date in these
         * documentation elements.
         *
         * @return a string representing the current timestamp, or null
         */
        protected String getDateString() {
            if (suppressDate) {
                return null;
            } else if (dateFormat != null) {
                return dateFormat.format(new Date());
            } else {
                return new Date().toString();
            }
        }
    
        @Override
        public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) {
            if (suppressAllComments) {
                return;
            }
            innerClass.addJavaDocLine("/**");
            innerClass.addJavaDocLine(" * ");
            String remarks = introspectedTable.getRemarks();
            if (addRemarkComments && StringUtility.stringHasValue(remarks)) {
                String[] remarkLines = remarks.split(System.getProperty("line.separator"));
                for (String remarkLine : remarkLines) {
                    innerClass.addJavaDocLine(" * <p>" + remarkLine);
                }
            }
            innerClass.addJavaDocLine(" * ");
            innerClass.addJavaDocLine(" * @author " + userName);
            innerClass.addJavaDocLine(" * @date " + getDateString());
    
    
            innerClass.addJavaDocLine(" */");
        }
    
        @Override
        public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) {
            addClassComment(innerClass, introspectedTable);
        }
    
        /**
         * 创建的数据表对应的类添加的注释
         */
        @Override
        public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
            if (suppressAllComments) {
                return;
            }
            topLevelClass.addJavaDocLine("/**");
            topLevelClass.addJavaDocLine(" * ");
            String remarks = introspectedTable.getRemarks();
            if (addRemarkComments && StringUtility.stringHasValue(remarks)) {
                String[] remarkLines = remarks.split(System.getProperty("line.separator"));
                for (String remarkLine : remarkLines) {
                    topLevelClass.addJavaDocLine(" * " + remarkLine);
                }
            }
            topLevelClass.addJavaDocLine(" * ");
            topLevelClass.addJavaDocLine(" * @author " + userName);
            topLevelClass.addJavaDocLine(" * @version 1.0");
            topLevelClass.addJavaDocLine(" * @since " + getDateString());
            topLevelClass.addJavaDocLine(" * ");
            topLevelClass.addJavaDocLine(" * Copyright by Longser Technologies Ltd. ");
            topLevelClass.addJavaDocLine(" */");
        }
    
        @Override
        public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) {
            if (suppressAllComments) {
                return;
            }
            innerEnum.addJavaDocLine("/**");
            innerEnum.addJavaDocLine(" * ");
            String remarks = introspectedTable.getRemarks();
            if (addRemarkComments && StringUtility.stringHasValue(remarks)) {
                String[] remarkLines = remarks.split(System.getProperty("line.separator"));
                for (String remarkLine : remarkLines) {
                    innerEnum.addJavaDocLine(" * " + remarkLine);
                }
            }
    
            innerEnum.addJavaDocLine(" * @author " + userName);
            innerEnum.addJavaDocLine(" * @date " + getDateString());
    
    
            innerEnum.addJavaDocLine(" */");
        }
    
        /**
         * <p>生成xx.java文件(model)属性的注释</p>
         */
        @Override
        public void addFieldComment(Field field, IntrospectedTable introspectedTable,
                                    IntrospectedColumn introspectedColumn) {
            if (suppressAllComments) {
                return;
            }
    
            field.addJavaDocLine("/**");
    
            // 获取列注释并加入到注解中
            String remarks = introspectedColumn.getRemarks();
            if (addRemarkComments && StringUtility.stringHasValue(remarks)) {
                String[] remarkLines = remarks.split(System.getProperty("line.separator"));
                for (String remarkLine : remarkLines) {
                    field.addJavaDocLine(" * " + remarkLine);
                }
            }
    
            field.addJavaDocLine(" */");
        }
    
        @Override
        public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
        }
    
        /**
         * xxxMapper接口和xxxExample类方法注解
         */
        @Override
        public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {
            if (suppressAllComments) {
                return;
            }
    
            method.addJavaDocLine("/**");
    
            List<Parameter> parameters = method.getParameters();
            for(Parameter parameter : parameters) {
                String sb = " * @param " +
                        parameter.getName();
                method.addJavaDocLine(sb);
            }
    
            Optional<FullyQualifiedJavaType> returnType = method.getReturnType();
            returnType.ifPresent(x -> method.addJavaDocLine(" * @return " + x.getShortName()));
    
            method.addJavaDocLine(" */");
        }
    
        @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) {
            addGeneralMethodComment(method, introspectedTable);
        }
    
        @Override
        public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable,
                                               IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
            addGeneralMethodComment(method, introspectedTable);
        }
    
        @Override
        public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable,
                                       Set<FullyQualifiedJavaType> imports) {
            addFieldComment(field, introspectedTable);
        }
    
        @Override
        public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable,
                                       IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
            addFieldComment(field, introspectedTable, introspectedColumn);
        }
    
        @Override
        public void addClassAnnotation(InnerClass innerClass, IntrospectedTable introspectedTable,
                                       Set<FullyQualifiedJavaType> imports) {
        }
    
        @SuppressWarnings("unused")
        private String getGeneratedAnnotation(String comment) {
            StringBuilder buffer = new StringBuilder();
            buffer.append("@Generated(");
            if (suppressAllComments) {
                buffer.append('\"');
            } else {
                buffer.append("value=\"");
            }
    
            buffer.append(MyBatisGenerator.class.getName());
            buffer.append('\"');
    
            if (!suppressDate && !suppressAllComments) {
                buffer.append(", date=\"");
                buffer.append(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now()));
                buffer.append('\"');
            }
    
            if (!suppressAllComments) {
                buffer.append(", comments=\"");
                buffer.append(comment);
                buffer.append('\"');
            }
    
            buffer.append(')');
            return buffer.toString();
        }
    
        @Override
        public void addFileComment(KotlinFile kotlinFile) {
        }
    }
    
    package com.longser.mybatis.generator.plugins;
    
    import org.mybatis.generator.api.IntrospectedColumn;
    import org.mybatis.generator.api.IntrospectedTable;
    import org.mybatis.generator.api.PluginAdapter;
    import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
    import org.mybatis.generator.api.dom.java.Interface;
    import org.mybatis.generator.api.dom.java.Method;
    import org.mybatis.generator.api.dom.java.TopLevelClass;
    import org.mybatis.generator.config.PropertyRegistry;
    import org.mybatis.generator.internal.util.StringUtility;
    
    import java.text.SimpleDateFormat;
    import java.util.*;
    
    import static org.mybatis.generator.internal.util.StringUtility.isTrue;
    
    /**
     * @author Sin
     * @date 2019/04/04/11:15
     */
    @SuppressWarnings("unused")
    public class LombokPlugin extends PluginAdapter {
    
        private final Collection<Annotations> annotations;
    
        /**
         * 抑制日期  默认false:不抑制
         */
        private final boolean suppressDate;
        /**
         * 抑制注释 默认false:不抑制
         */
        private final boolean suppressAllComments;
    
        /**
         * 日期格式
         */
        private SimpleDateFormat dateFormat;
    
        /**
         * 当前用户的名字
         */
        private final String userName;
    
        /**
         * LombokPlugin constructor
         */
        public LombokPlugin() {
            super();
    
            annotations = new LinkedHashSet<>(Annotations.values().length);
    
            Properties properties = new Properties();
    
            suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE));
            suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));
    
            String dateFormatString = properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_DATE_FORMAT);
            if (StringUtility.stringHasValue(dateFormatString)) {
                dateFormat = new SimpleDateFormat(dateFormatString);
            }
    
            userName = System.getProperty("user.name");
        }
    
        /**
         * Returns a formated date string to include in the Javadoc tag and XML
         * comments. You may return null if you do not want the date in these
         * documentation elements.
         *
         * @return a string representing the current timestamp, or null
         */
        protected String getDateString() {
            if (suppressDate) {
                return null;
            } else if (dateFormat != null) {
                return dateFormat.format(new Date());
            } else {
                return new Date().toString();
            }
        }
    
        /**
         * @param list  warnings list of warnings
         * @return always true
         */
        @Override
        public boolean validate(List<String> list) {
            return true;
        }
    
        /**
         * Intercepts base record class generation
         *
         * @param topLevelClass     the generated base record class
         * @param introspectedTable The class containing information about the table as
         *                          introspected from the database
         * @return always true
         */
        @Override
        public boolean modelBaseRecordClassGenerated(
                TopLevelClass topLevelClass,
                IntrospectedTable introspectedTable
        ) {
            addAnnotations(topLevelClass);
    
            //实体类的import
            //topLevelClass.addImportedType("java.io.Serializable");
    
            //接口
            //topLevelClass.addSuperInterface(new FullyQualifiedJavaType("java.io.Serializable"));
            return true;
        }
    
    
        /**
         * Intercepts primary key class generation
         *
         * @param topLevelClass     the generated primary key class
         * @param introspectedTable The class containing information about the table as
         *                          introspected from the database
         * @return always true
         */
        @Override
        public boolean modelPrimaryKeyClassGenerated(
                TopLevelClass topLevelClass,
                IntrospectedTable introspectedTable
        ) {
            addAnnotations(topLevelClass);
            return true;
        }
    
        /**
         * Intercepts "record with blob" class generation
         *
         * @param topLevelClass     the generated record with BLOBs class
         * @param introspectedTable The class containing information about the table as
         *                          introspected from the database
         * @return always true
         */
        @Override
        public boolean modelRecordWithBLOBsClassGenerated(
                TopLevelClass topLevelClass,
                IntrospectedTable introspectedTable
        ) {
            addAnnotations(topLevelClass);
            return true;
        }
    
        @Override
        public void setProperties(Properties properties) {
            super.setProperties(properties);
    
            //@Data is default annotation
            annotations.add(Annotations.DATA);
    
            for (String annotationName : properties.stringPropertyNames()) {
                if (annotationName.contains(".")) {
                    // Not an annotation name
                    continue;
                }
                String value = properties.getProperty(annotationName);
                if (!Boolean.parseBoolean(value)) {
                    // The annotation is disabled, skip it
                    continue;
                }
                Annotations annotation = Annotations.getValueOf(annotationName);
                if (annotation == null) {
                    continue;
                }
                String optionsPrefix = annotationName + ".";
                for (String propertyName : properties.stringPropertyNames()) {
                    if (!propertyName.startsWith(optionsPrefix)) {
                        // A property not related to this annotation
                        continue;
                    }
                    String propertyValue = properties.getProperty(propertyName);
                    annotation.appendOptions(propertyName, propertyValue);
                }
                annotations.add(annotation);
                annotations.addAll(Annotations.getDependencies(annotation));
            }
        }
    
        @Override
        public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) {
            //Mapper文件的注释
            if(!suppressAllComments) {
                interfaze.addJavaDocLine("/**");
                interfaze.addJavaDocLine(" * ");
    
                String remarks = introspectedTable.getRemarks();
                if (StringUtility.stringHasValue(remarks)) {
                    String[] remarkLines = remarks.split(System.getProperty("line.separator"));
                    for (String remarkLine : remarkLines) {
                        interfaze.addJavaDocLine(" * " + remarkLine + " 映射定义");
                    }
                }
                interfaze.addJavaDocLine(" * ");
                interfaze.addJavaDocLine(" * @author " + userName);
                interfaze.addJavaDocLine(" * @version 1.0");
                interfaze.addJavaDocLine(" * @since " + getDateString());
                interfaze.addJavaDocLine(" * ");
                interfaze.addJavaDocLine(" * Copyright by Longser Technologies Ltd. ");
    
                interfaze.addJavaDocLine(" */");
            }
            return true;
        }
    
        @Override
        public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
            //不生成getter
            return false;
        }
    
        @Override
        public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
            //不生成setter
            return false;
        }
    
        /**
         * Adds the lombok annotations' imports and annotations to the class
         *
         * @param topLevelClass the partially implemented model class
         */
        private void addAnnotations(TopLevelClass topLevelClass) {
            for (Annotations annotation : annotations) {
                topLevelClass.addImportedType(annotation.javaType);
                topLevelClass.addAnnotation(annotation.asAnnotation());
            }
        }
    
        private enum Annotations {
            DATA("data", "@Data", "lombok.Data"),
            BUILDER("builder", "@Builder", "lombok.Builder"),
            ALL_ARGS_CONSTRUCTOR("allArgsConstructor", "@AllArgsConstructor", "lombok.AllArgsConstructor"),
            NO_ARGS_CONSTRUCTOR("noArgsConstructor", "@NoArgsConstructor", "lombok.NoArgsConstructor"),
            ACCESSORS("accessors", "@Accessors", "lombok.experimental.Accessors"),
            TO_STRING("toString", "@ToString", "lombok.ToString");
    
    
            private final String paramName;
            private final String name;
            private final FullyQualifiedJavaType javaType;
            private final List<String> options;
    
    
            Annotations(String paramName, String name, String className) {
                this.paramName = paramName;
                this.name = name;
                this.javaType = new FullyQualifiedJavaType(className);
                this.options = new ArrayList<>();
            }
    
            private static Annotations getValueOf(String paramName) {
                for (Annotations annotation : Annotations.values()) {
                    if (String.CASE_INSENSITIVE_ORDER.compare(paramName, annotation.paramName) == 0) {
                        return annotation;
                    }
                }
    
                return null;
            }
    
            private static Collection<Annotations> getDependencies(Annotations annotation) {
                if (annotation == ALL_ARGS_CONSTRUCTOR) {
                    return Collections.singleton(NO_ARGS_CONSTRUCTOR);
                } else {
                    return Collections.emptyList();
                }
            }
    
            // A trivial quoting.
            // Because Lombok annotation options type is almost String or boolean.
            private static String quote(String value) {
                if (Boolean.TRUE.toString().equals(value) || Boolean.FALSE.toString().equals(value)) {
                    // case of boolean, not passed as an array.
                    return value;
                }
                return value.replaceAll("[\\w]+", "\"$0\"");
            }
    
            private void appendOptions(String key, String value) {
                String keyPart = key.substring(key.indexOf(".") + 1);
                String valuePart = value.contains(",") ? String.format("{%s}", value) : value;
                this.options.add(String.format("%s=%s", keyPart, quote(valuePart)));
            }
    
            private String asAnnotation() {
                if (options.isEmpty()) {
                    return name;
                }
                StringBuilder sb = new StringBuilder();
                sb.append(name);
                sb.append("(");
                boolean first = true;
                for (String option : options) {
                    if (first) {
                        first = false;
                    } else {
                        sb.append(", ");
                    }
                    sb.append(option);
                }
                sb.append(")");
                return sb.toString();
            }
        }
    
    }
    

    执行 Maven 项目的 package 和 deploy,就可以在你本地的依赖库中部署好生成器的 jar 文件

    下面是在Mac OS 系统中部署后的情况
    image.png