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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容