程序员

mybatis generator插件编写

2017-12-27  本文已影响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文件:

如果生成的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进行插件的生成

上一篇 下一篇

猜你喜欢

热点阅读