mybatis generator插件編寫

[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進行插件的生成

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容