美文网首页程序员
mybatis generator插件编写

mybatis generator插件编写

作者: 三无架构师 | 来源:发表于2017-12-27 17:59 被阅读155次

    [TOC]

    MyBatis Generator Plugin

    Plugin用来在生成Java及XML的过程中修改或者添加内容。

    其必须实现com.mybatis.generator.api.Plugin接口。大多数插件应扩展适配器类org.mybatis.generator.api.PluginAdapter 。适配器类提供基本的插件支持,并为大多数的接口方法(类似于Swing适配器类)提供了空操作的方法。

    插件的生命周期

    1. 插件通过默认的构造函数创建
    2. setContext方法被调用
    3. setProperties方法被调用
    4. validate方法被调用。如果该方法返回false ,那么插件中的其他方法都不会再被调用。
    5. 对于配置中的每个表:
    6. initialized方法被调用
    7. Java客户端的方法:
      1. clientXXXMethodGenerated(Method, TopLevelClass, IntrospectedTable) - 当Java客户端实现类生成的时候这些方法被调用.
      2. clientXXXMethodGenerated(Method, Interface, IntrospectedTable) -当Java客户端接口生成的时候这些方法被调用。
      3. clientGenerated(Interface, TopLevelClass, IntrospectedTable)方法被调用
    8. 模型方法:
      1. modelFieldGenerated, modelGetterMethodGenerated, modelSetterMethodGenerated for each field in the class
      2. modelExampleClassGenerated(TopLevelClass, IntrospectedTable)
      3. modelPrimaryKeyClassGenerated(TopLevelClass, IntrospectedTable)
      4. modelBaseRecordClassGenerated(TopLevelClass, IntrospectedTable)
      5. modelRecordWithBLOBsClassGenerated(TopLevelClass, IntrospectedTable)
    9. SQL映射方法:
      1. sqlMapXXXElementGenerated(XmlElement, IntrospectedTable) - 当生成SQL映射的每个元素的时候这些方法被调用
      2. sqlMapDocumentGenerated(Document, IntrospectedTable)
      3. sqlMapDocument(GeneratedXmlFile, IntrospectedTable)
    10. contextGenerateAdditionalJavaFiles(IntrospectedTable)方法被调用
    11. contextGenerateAdditionalXmlFiles(IntrospectedTable)方法被调用
    12. contextGenerateAdditionalJavaFiles()方法被调用
    13. contextGenerateAdditionalXmlFiles()方法被调用

    可以在以下方法中生成自定义的xml或者Java文件:

    • contextGenerateAdditionalJavaFiles(IntrospectedTable)
    • contextGenerateAdditionalXmlFiles(IntrospectedTable)
    • contextGenerateAdditionalJavaFiles()
    • contextGenerateAdditionalXmlFiles()

    如果生成的xml或者Java文件和当前的配置中的表相关,如需要根据每个表的xml及client生成新的自定义的xml或client,则使用带有参数的:

    contextGenerateAdditionalJavaFiles(IntrospectedTable)
    contextGenerateAdditionalXmlFiles(IntrospectedTable)
    

    否则可以使用不带参数的:

    contextGenerateAdditionalJavaFiles()
    contextGenerateAdditionalXmlFiles()
    

    如我们需要生成mybatis-config.xml配置文件,该文件和具体的表无关,则可以使用contextGenerateAdditionalXmlFiles().
    可以参考muybatis-generator-core包里面plugin目录下的SqlMapConfigPlugin

    生成自定义Mapper及xml

    如果我们把自己的业务写在默认的Mapper.java及Mapper.xml中时,如果业务很多,会发现代码很乱,如果想和默认的进行区分,
    并且方便重新生成,则编写插件进行生成。

    目的:

    1. 支持对生成的Mapper进行重命名,如需要把默认的Mapper生成为Dao
    2. 支持把默认的Mapper.java生成在mbg目录下,Mapper.xml生成在相应的mbg目录下
    3. 支持在custom目录生成新的Mappper.java及xml

    其生成结构如:

    src
    ├── main
    │  ├── java
    │  │  └── com
    │  │      ├── demo
    │  │      │  └── monitor
    │  │      │      └── aly
    │  │      │          ├── App.java
    │  │      │          ├── config
    │  │      │          │  └── AppConfig.java
    │  │      │          ├── controller
    │  │      │          │  └── IndexController.java
    │  │      │          ├── dao
    │  │      │          │  ├── custom
    │  │      │          │  │  ├── EcsInfoMapper.java
    │  │      │          │  │  └── SlbInfoMapper.java
    │  │      │          │  └── mbg
    │  │      │          │      ├── EcsInfoMBGMapper.java
    │  │      │          │      └── SlbInfoMBGMapper.java
    │  │      │          ├── model
    │  │      │          │  ├── EcsInfo.java
    │  │      │          │  └── SlbInfo.java
    │  │      │          └── service
    │  │      │              └── EcsInfoService.java
    │  │      └── kkk
    │  └── resources
    │      ├── application.yml
    │      ├── generatorConfig.xml
    │      ├── log4j2.xml
    │      ├── mapper
    │      │  ├── custom
    │      │  │  ├── EcsInfoMapper.xml
    │      │  │  └── SlbInfoMapper.xml
    │      │  └── mbg
    │      │      ├── EcsInfoMBGMapper.xml
    │      │      └── SlbInfoMBGMapper.xml
    │      └── mybatis-config.xml
    └── test
        └── java
    

    其代码如下:

    import org.mybatis.generator.api.GeneratedJavaFile;
    import org.mybatis.generator.api.GeneratedXmlFile;
    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.JavaVisibility;
    import org.mybatis.generator.api.dom.xml.Attribute;
    import org.mybatis.generator.api.dom.xml.Document;
    import org.mybatis.generator.api.dom.xml.XmlElement;
    import org.mybatis.generator.codegen.XmlConstants;
    import org.mybatis.generator.internal.util.StringUtility;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class RenamePlugin extends PluginAdapter {
        private String searchStr;
        private String replaceStr;
        private Pattern pattern;
        private boolean replaceFlag;
    
        @Override
        public boolean validate(List<String> list) {
            searchStr = properties.getProperty("searchString");
            replaceStr = properties.getProperty("replaceString");
            boolean valid = StringUtility.stringHasValue(searchStr) && StringUtility.stringHasValue(replaceStr);
    
            if (valid) {
                pattern = Pattern.compile(searchStr);
                replaceFlag = true;
            } else {
                searchStr = "";
                replaceStr = "";
            }
    
            return true;
        }
    
        /**
        * 重命名及更改默认的目录
        * @param introspectedTable
        */
        @Override
        public void initialized(IntrospectedTable introspectedTable) {
            //更改默认生成的Mapper.java为mbg目录下MBGMapper.java
            String oldType = introspectedTable.getMyBatis3JavaMapperType();
            if (replaceFlag) {
                Matcher matcher = pattern.matcher(oldType);
                oldType = matcher.replaceAll("MBG" + replaceStr);
            } else {
                oldType = oldType.replaceAll("Mapper", "MBGMapper");
            }
            int idx = oldType.lastIndexOf(".");
            if (idx > 0) {
                oldType = oldType.substring(0, idx) + ".mbg" + oldType.substring(idx);
            }
            introspectedTable.setMyBatis3JavaMapperType(oldType);
            //更改默认生成的Mapper.java为mbg目录下MBGMapper.java
            String mapperName = introspectedTable.getMyBatis3XmlMapperFileName();
            if (replaceFlag) {
                Matcher matcher = pattern.matcher(oldType);
                mapperName = matcher.replaceAll("MBG" + replaceStr);
            } else {
                mapperName = mapperName.replaceAll("Mapper", "MBGMapper");
            }
            introspectedTable.setMyBatis3XmlMapperFileName(mapperName);
            String mapperPkg = introspectedTable.getMyBatis3XmlMapperPackage() + File.separator + "mbg";
            introspectedTable.setMyBatis3XmlMapperPackage(mapperPkg);
        }
    
        @Override
        public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
            List<GeneratedJavaFile> result = new ArrayList<>();
            GeneratedJavaFile g = null;
            for (GeneratedJavaFile f : introspectedTable.getGeneratedJavaFiles()) {
                if (f.getFileName().contains("Dao") || f.getFileName().contains("Mapper")) {
                    g = f;
                    break;
                }
            }
            if (g != null) {
                String pkgName = g.getTargetPackage().replace("mbg", "custom");
                String className = g.getCompilationUnit().getType().getShortName().replace("MBG", "");
                Interface customInterface = new Interface(pkgName + "." + className);
                customInterface.setVisibility(JavaVisibility.PUBLIC);
    
                FullyQualifiedJavaType daoType = new FullyQualifiedJavaType(g.getCompilationUnit().getType().getFullyQualifiedName());
                customInterface.addSuperInterface(daoType);
                customInterface.addImportedType(daoType);
                String target = g.getTargetProject();
                String fileName = (target + File.separator + pkgName + "." + className).replace(".", File.separator);
                File file = new File(fileName + ".java");
                if (!file.exists()) {
                    GeneratedJavaFile tmp = new GeneratedJavaFile(customInterface, target, context.getJavaFormatter());
                    result.add(tmp);
                }
            }
            return result;
        }
    
        /**
        * 为相应的默认的xml文件生成一个自定义的xml,自己实现的可以都写在该文件中
        * @param introspectedTable
        * @return
        */
        @Override
        public List<GeneratedXmlFile> contextGenerateAdditionalXmlFiles(IntrospectedTable introspectedTable) {
            List<GeneratedXmlFile> result = new ArrayList<>();
            GeneratedXmlFile mbgXml = introspectedTable.getGeneratedXmlFiles().get(0);
            String projectName = mbgXml.getTargetProject();
            String packageName = mbgXml.getTargetPackage().replace("mbg", "custom");
            GeneratedJavaFile g = null;
            for (GeneratedJavaFile f : introspectedTable.getGeneratedJavaFiles()) {
                if (f.getFileName().contains("Dao") || f.getFileName().contains("Mapper")) {
                    g = f;
                    break;
                }
            }
            if (g != null) {
                Document document = new Document(XmlConstants.MYBATIS3_MAPPER_CONFIG_PUBLIC_ID,
                        XmlConstants.MYBATIS3_MAPPER_SYSTEM_ID);
                XmlElement root = new XmlElement("mapper");
                String className = g.getFileName().replace("MBG", "");
                String fileName = g.getFileName().replace("MBG", "").replace(".java", ".xml");
                String pkgName = g.getTargetPackage().replace(".mbg", ".custom");
                Attribute attribute = new Attribute("namespace", pkgName + "." + className.replace(".java", ""));
                root.addAttribute(attribute);
                document.setRootElement(root);
    
                File file = new File(projectName + File.separator + packageName + File.separator + fileName);
                if (!file.exists()) {
                    GeneratedXmlFile gxf = new GeneratedXmlFile(document, fileName, packageName,
                            projectName, false, context.getXmlFormatter());
                    result.add(gxf);
                }
            }
            return result;
        }
    }
    

    自定义插件

    功能:美化model的生成样式,其中属性注释为:列名 : 列注释

    package com.liukun.mgenerator;
    
    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.Field;
    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 java.util.List;
    
    /**
     * Created by HFJY on 2017/6/30.
     */
    public class Demo extends PluginAdapter {
        private void print(Throwable throwable) {
            System.out.println(throwable.getStackTrace()[0].getMethodName());
        }
    
        @Override
        public boolean validate(List<String> list) {
            return true;
        }
    
        @Override
        public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
            method.getJavaDocLines().set(1," * clientDeleteByPrimaryKeyMethodGenerated!测试");
            method.getJavaDocLines().remove(2);
            return super.clientDeleteByPrimaryKeyMethodGenerated(method, interfaze, introspectedTable);
        }
    
        @Override
        public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
            field.getJavaDocLines().set(1," * " + introspectedColumn.getActualColumnName() + " : " + introspectedColumn.getRemarks());
            field.getJavaDocLines().remove(2);
            field.getJavaDocLines().remove(2);
            return super.modelFieldGenerated(field, topLevelClass, introspectedColumn, introspectedTable, modelClassType);
        }
    
        @Override
        public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
            method.getJavaDocLines().remove(1);
            method.getJavaDocLines().remove(1);
            return super.modelGetterMethodGenerated(method, topLevelClass, introspectedColumn, introspectedTable, modelClassType);
        }
    
        @Override
        public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
            method.getJavaDocLines().remove(1);
            method.getJavaDocLines().remove(1);
            return super.modelSetterMethodGenerated(method, topLevelClass, introspectedColumn, introspectedTable, modelClassType);
        }
    }
    

    项目进行打包,其它项目在maven中引用该插件

    <plugin>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>1.3.5</version>
        <configuration>
            <overwrite>true</overwrite>
        </configuration>
        <dependencies>
            <dependency>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-core</artifactId>
                <version>1.3.5</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.38</version>
            </dependency>
            <dependency>
                <groupId>com.liukun.mybatis.generator</groupId>
                <artifactId>demogenerator</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </plugin>
    

    并且在resources/generatorConfig.xml中相应的context下引入该插件即可:

    <plugin type="com.liukun.mgenerator.Demo"></plugin>
    

    这时就可以通过mvn mybatis-generator:generate进行插件的生成

    相关文章

      网友评论

        本文标题:mybatis generator插件编写

        本文链接:https://www.haomeiwen.com/subject/crzugxtx.html