欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

mybatis-generator扩展

程序员文章站 2022-12-23 19:00:08
在新公司的新项目想用mybatis-generator来生成DAO层,有同事提出一些改进意见,遂获得源码后进行小幅改造。 目标: 中文注释,精简注释 Model类使用lombok简化 增加selectOneByExample方法(较多的使用唯一索引查询场景) 首先获得源码 在任一项目中引入jar包, ......

在新公司的新项目想用mybatis-generator来生成dao层,有同事提出一些改进意见,遂获得源码后进行小幅改造。

目标:

  • 中文注释,精简注释
  • model类使用lombok简化
  • 增加selectonebyexample方法(较多的使用唯一索引查询场景)

首先获得源码

在任一项目中引入jar包,使用maven download sources获取源码,最新版本1.3.7

<dependency>
    <groupid>org.mybatis.generator</groupid>
    <artifactid>mybatis-generator-core</artifactid>
    <version>1.3.7</version>
</dependency>

构建项目

新建一个maven项目,设置groupid和artifactid

<groupid>com.mine.generator</groupid>
<artifactid>mybatis-generator-core</artifactid>
<version>1.0-snapshot</version>

把解压后的源码复制到目录

mybatis-generator扩展

在pom.xml中添加项目依赖

mybatis-generator扩展
<dependencies>
        <dependency>
            <groupid>log4j</groupid>
            <artifactid>log4j</artifactid>
            <scope>provided</scope>
            <version>1.2.17</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupid>org.slf4j</groupid>
            <artifactid>slf4j-api</artifactid>
            <scope>provided</scope>
            <version>1.7.25</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupid>org.apache.logging.log4j</groupid>
            <artifactid>log4j-api</artifactid>
            <scope>provided</scope>
            <version>2.11.0</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupid>commons-logging</groupid>
            <artifactid>commons-logging</artifactid>
            <scope>provided</scope>
            <version>1.2</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupid>org.apache.ant</groupid>
            <artifactid>ant</artifactid>
            <scope>provided</scope>
            <version>1.10.4</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupid>org.junit.vintage</groupid>
            <artifactid>junit-vintage-engine</artifactid>
            <version>5.2.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupid>org.hsqldb</groupid>
            <artifactid>hsqldb</artifactid>
            <version>2.4.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupid>com.github.javaparser</groupid>
            <version>3.6.12</version>
            <artifactid>javaparser-core</artifactid>
        </dependency>
</dependencies>
view code

功能拓展

model中文注释、精简其他注释

修改生成注释默认用的defaultcommentgenerator

mybatis-generator扩展
package org.mybatis.generator.internal;

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.*;
import org.mybatis.generator.api.dom.xml.xmlelement;
import org.mybatis.generator.internal.util.stringutility;

import java.text.simpledateformat;
import java.time.zoneddatetime;
import java.time.format.datetimeformatter;
import java.util.date;
import java.util.properties;
import java.util.set;

/**
 * @author jeff butler
 */
public class defaultcommentgenerator implements commentgenerator {
    private simpledateformat dateformat = new simpledateformat("yyyy-mm-dd hh:mm:ss");

    public defaultcommentgenerator() {
        super();
    }

    @override
    public void addjavafilecomment(compilationunit compilationunit) {
    }

    @override
    public void addcomment(xmlelement xmlelement) {
    }

    @override
    public void addrootcomment(xmlelement rootelement) {
    }

    @override
    public void addconfigurationproperties(properties properties) {
    }

    protected string getdatestring() {
        return dateformat.format(new date());
    }

    @override
    public void addclasscomment(innerclass innerclass,
                                introspectedtable introspectedtable) {
    }

    @override
    public void addclasscomment(innerclass innerclass,
                                introspectedtable introspectedtable, boolean markasdonotdelete) {
    }

    @override
    public void addmodelclasscomment(toplevelclass toplevelclass,
                                     introspectedtable introspectedtable) {
        toplevelclass.addjavadocline("/**");
        toplevelclass.addjavadocline(" * 生成日期:" + getdatestring());
        toplevelclass.addjavadocline(" * 表名: " + introspectedtable.getfullyqualifiedtable().tostring());
        toplevelclass.addjavadocline(" */");
    }

    @override
    public void addenumcomment(innerenum innerenum,
                               introspectedtable introspectedtable) {
    }

    @override
    public void addfieldcomment(field field,
                                introspectedtable introspectedtable,
                                introspectedcolumn introspectedcolumn) {
        field.addjavadocline("/**");
        field.addjavadocline(" * " + introspectedcolumn.getremarks());
        field.addjavadocline(" */");
    }

    @override
    public void addfieldcomment(field field, introspectedtable introspectedtable) {
    }

    @override
    public void addgeneralmethodcomment(method method,
                                        introspectedtable introspectedtable) {
    }

    @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) {
        imports.add(new fullyqualifiedjavatype("javax.annotation.generated"));
        string comment = "source table: " + introspectedtable.getfullyqualifiedtable().tostring();
        method.addannotation(getgeneratedannotation(comment));
    }

    @override
    public void addgeneralmethodannotation(method method, introspectedtable introspectedtable,
                                           introspectedcolumn introspectedcolumn, set<fullyqualifiedjavatype> imports) {
        imports.add(new fullyqualifiedjavatype("javax.annotation.generated"));
        string comment = "source field: "
                + introspectedtable.getfullyqualifiedtable().tostring()
                + "."
                + introspectedcolumn.getactualcolumnname();
        method.addannotation(getgeneratedannotation(comment));
    }

    @override
    public void addfieldannotation(field field, introspectedtable introspectedtable,
                                   set<fullyqualifiedjavatype> imports) {
        imports.add(new fullyqualifiedjavatype("javax.annotation.generated"));
        string comment = "source table: " + introspectedtable.getfullyqualifiedtable().tostring();
        field.addannotation(getgeneratedannotation(comment));
    }

    @override
    public void addfieldannotation(field field, introspectedtable introspectedtable,
                                   introspectedcolumn introspectedcolumn, set<fullyqualifiedjavatype> imports) {
        imports.add(new fullyqualifiedjavatype("javax.annotation.generated"));
        string comment = "source field: "
                + introspectedtable.getfullyqualifiedtable().tostring()
                + "."
                + introspectedcolumn.getactualcolumnname();
        field.addannotation(getgeneratedannotation(comment));

        string remarks = introspectedcolumn.getremarks();
        if (stringutility.stringhasvalue(remarks)) {
            field.addjavadocline("/**");
            field.addjavadocline(" * database column remarks:");
            string[] remarklines = remarks.split(system.getproperty("line.separator"));
            for (string remarkline : remarklines) {
                field.addjavadocline(" *   " + remarkline);
            }
            field.addjavadocline(" */");
        }
    }

    @override
    public void addclassannotation(innerclass innerclass, introspectedtable introspectedtable,
                                   set<fullyqualifiedjavatype> imports) {
        imports.add(new fullyqualifiedjavatype("javax.annotation.generated"));
        string comment = "source table: " + introspectedtable.getfullyqualifiedtable().tostring();
        innerclass.addannotation(getgeneratedannotation(comment));
    }

    private string getgeneratedannotation(string comment) {
        stringbuilder buffer = new stringbuilder();
        buffer.append("@generated(");
        buffer.append("value=\"");

        buffer.append(mybatisgenerator.class.getname());
        buffer.append('\"');

        buffer.append(", date=\"");
        buffer.append(datetimeformatter.iso_offset_date_time.format(zoneddatetime.now()));
        buffer.append('\"');

        buffer.append(", comments=\"");
        buffer.append(comment);
        buffer.append('\"');

        buffer.append(')');
        return buffer.tostring();
    }
}
view code

model类使用lombok简化

修改baserecordgenerator的getcompilationunits的方法即可

  public list<compilationunit> getcompilationunits() {
        fullyqualifiedtable table = introspectedtable.getfullyqualifiedtable();
        progresscallback.starttask(getstring(
                "progress.8", table.tostring())); //$non-nls-1$
        plugin plugins = context.getplugins();
        commentgenerator commentgenerator = context.getcommentgenerator();

        fullyqualifiedjavatype type = new fullyqualifiedjavatype(
                introspectedtable.getbaserecordtype());
        toplevelclass toplevelclass = new toplevelclass(type);
        toplevelclass.addimportedtype("lombok.getter");// 导入lombok类
        toplevelclass.addimportedtype("lombok.setter");

        toplevelclass.setvisibility(javavisibility.public);
        commentgenerator.addjavafilecomment(toplevelclass);

        fullyqualifiedjavatype superclass = getsuperclass();
        if (superclass != null) {
            toplevelclass.setsuperclass(superclass);
            toplevelclass.addimportedtype(superclass);
        }
        commentgenerator.addmodelclasscomment(toplevelclass, introspectedtable);
        toplevelclass.addannotation("@getter");// 增加lombok注解
        toplevelclass.addannotation("@setter");
        list<introspectedcolumn> introspectedcolumns = getcolumnsinthisclass();

        if (introspectedtable.isconstructorbased()) {
            addparameterizedconstructor(toplevelclass, introspectedtable.getnonblobcolumns());

            if (includeblobcolumns()) {
                addparameterizedconstructor(toplevelclass, introspectedtable.getallcolumns());
            }

            if (!introspectedtable.isimmutable()) {
                adddefaultconstructor(toplevelclass);
            }
        }

        string rootclass = getrootclass();
        for (introspectedcolumn introspectedcolumn : introspectedcolumns) {
            if (rootclassinfo.getinstance(rootclass, warnings)
                    .containsproperty(introspectedcolumn)) {
                continue;
            }

            field field = getjavabeansfield(introspectedcolumn, context, introspectedtable);
            if (plugins.modelfieldgenerated(field, toplevelclass,
                    introspectedcolumn, introspectedtable,
                    plugin.modelclasstype.base_record)) {
                toplevelclass.addfield(field);
                toplevelclass.addimportedtype(field.gettype());
            }

        }

        list<compilationunit> answer = new arraylist<>();
        if (context.getplugins().modelbaserecordclassgenerated(
                toplevelclass, introspectedtable)) {
            answer.add(toplevelclass);
        }
        return answer;
  }

增加selectonebyexample

首先查看类似的方法selectbyexample是怎么生成的,然后参考增加这个方法。

在introspectedtable中增加方法

  public string getselectonebyexamplestatementid() {
        return "selectonebyexample";//可以跟其他源码一样设置成常量,这里简单处理
  }

增加一个selectonebyexamplemethodgenerator

mybatis-generator扩展
/**
 *    copyright 2006-2016 the original author or authors.
 *
 *    licensed under the apache license, version 2.0 (the "license");
 *    you may not use this file except in compliance with the license.
 *    you may obtain a copy of the license at
 *
 *       http://www.apache.org/licenses/license-2.0
 *
 *    unless required by applicable law or agreed to in writing, software
 *    distributed under the license is distributed on an "as is" basis,
 *    without warranties or conditions of any kind, either express or implied.
 *    see the license for the specific language governing permissions and
 *    limitations under the license.
 */
package org.mybatis.generator.codegen.mybatis3.javamapper.elements;

import org.mybatis.generator.api.dom.java.*;

import java.util.set;
import java.util.treeset;

/**
 *
 * @author jeff butler
 *
 */
public class selectonebyexamplemethodgenerator extends
        abstractjavamappermethodgenerator {

    public selectonebyexamplemethodgenerator() {
        super();
    }

    @override
    public void addinterfaceelements(interface interfaze) {
        set<fullyqualifiedjavatype> importedtypes = new treeset<>();
        fullyqualifiedjavatype type = new fullyqualifiedjavatype(
                introspectedtable.getexampletype());
        importedtypes.add(type);
        importedtypes.add(fullyqualifiedjavatype.getnewlistinstance());

        method method = new method();
        method.setvisibility(javavisibility.public);

        fullyqualifiedjavatype returntype = introspectedtable.getrules()
                .calculateallfieldsclass();
        method.setreturntype(returntype);

        method.setname(introspectedtable.getselectonebyexamplestatementid());
        method.addparameter(new parameter(type, "example")); //$non-nls-1$

        context.getcommentgenerator().addgeneralmethodcomment(method,
                introspectedtable);

        addmapperannotations(interfaze, method);

        if (context.getplugins()
                .clientselectbyexamplewithblobsmethodgenerated(method, interfaze,
                        introspectedtable)) {
            addextraimports(interfaze);
            interfaze.addimportedtypes(importedtypes);
            interfaze.addmethod(method);
        }
    }

    public void addmapperannotations(interface interfaze, method method) {
    }

    public void addextraimports(interface interfaze) {
    }
}
view code

增加一个selectonebyexampleelementgenerator

mybatis-generator扩展
/**
 *    copyright 2006-2016 the original author or authors.
 *
 *    licensed under the apache license, version 2.0 (the "license");
 *    you may not use this file except in compliance with the license.
 *    you may obtain a copy of the license at
 *
 *       http://www.apache.org/licenses/license-2.0
 *
 *    unless required by applicable law or agreed to in writing, software
 *    distributed under the license is distributed on an "as is" basis,
 *    without warranties or conditions of any kind, either express or implied.
 *    see the license for the specific language governing permissions and
 *    limitations under the license.
 */
package org.mybatis.generator.codegen.mybatis3.xmlmapper.elements;

import org.mybatis.generator.api.dom.xml.attribute;
import org.mybatis.generator.api.dom.xml.textelement;
import org.mybatis.generator.api.dom.xml.xmlelement;

import static org.mybatis.generator.internal.util.stringutility.stringhasvalue;

/**
 *
 * @author jeff butler
 *
 */
public class selectonebyexampleelementgenerator extends
        abstractxmlelementgenerator {

    public selectonebyexampleelementgenerator() {
        super();
    }

    @override
    public void addelements(xmlelement parentelement) {
        string fqjt = introspectedtable.getexampletype();

        xmlelement answer = new xmlelement("select"); //$non-nls-1$

        answer.addattribute(new attribute("id", //$non-nls-1$
                introspectedtable.getselectonebyexamplestatementid()));
        answer.addattribute(new attribute(
                "resultmap", introspectedtable.getbaseresultmapid())); //$non-nls-1$
        answer.addattribute(new attribute("parametertype", fqjt)); //$non-nls-1$

        context.getcommentgenerator().addcomment(answer);

        answer.addelement(new textelement("select")); //$non-nls-1$
        xmlelement ifelement = new xmlelement("if"); //$non-nls-1$
        ifelement.addattribute(new attribute("test", "distinct")); //$non-nls-1$ //$non-nls-2$
        ifelement.addelement(new textelement("distinct")); //$non-nls-1$
        answer.addelement(ifelement);

        stringbuilder sb = new stringbuilder();
        if (stringhasvalue(introspectedtable
                .getselectbyexamplequeryid())) {
            sb.append('\'');
            sb.append(introspectedtable.getselectbyexamplequeryid());
            sb.append("' as queryid,"); //$non-nls-1$
            answer.addelement(new textelement(sb.tostring()));
        }
        answer.addelement(getbasecolumnlistelement());

        sb.setlength(0);
        sb.append("from "); //$non-nls-1$
        sb.append(introspectedtable
                .getaliasedfullyqualifiedtablenameatruntime());
        answer.addelement(new textelement(sb.tostring()));
        answer.addelement(getexampleincludeelement());

        ifelement = new xmlelement("if"); //$non-nls-1$
        ifelement.addattribute(new attribute("test", "orderbyclause != null")); //$non-nls-1$ //$non-nls-2$
        ifelement.addelement(new textelement("order by ${orderbyclause}")); //$non-nls-1$
        answer.addelement(ifelement);

        if (context.getplugins()
                .sqlmapselectbyexamplewithoutblobselementgenerated(answer,
                        introspectedtable)) {
            parentelement.addelement(answer);
        }
        answer.addelement(new textelement("limit 1"));
    }
}
view code

修改javamappergenerator,在getcompilationunits方法中增加addselectonebyexamplemethod(interfaze),这里顺带把生成的代码排了个序,并且把不常用的几个方法给注释掉了。

@override
public list<compilationunit> getcompilationunits() {
progresscallback.starttask(getstring("progress.17", //$non-nls-1$
introspectedtable.getfullyqualifiedtable().tostring()));
commentgenerator commentgenerator = context.getcommentgenerator();

fullyqualifiedjavatype type = new fullyqualifiedjavatype(
introspectedtable.getmybatis3javamappertype());
interface interfaze = new interface(type);
interfaze.setvisibility(javavisibility.public);
commentgenerator.addjavafilecomment(interfaze);

string rootinterface = introspectedtable
.gettableconfigurationproperty(propertyregistry.any_root_interface);
if (!stringhasvalue(rootinterface)) {
rootinterface = context.getjavaclientgeneratorconfiguration()
.getproperty(propertyregistry.any_root_interface);
}

if (stringhasvalue(rootinterface)) {
fullyqualifiedjavatype fqjt = new fullyqualifiedjavatype(
rootinterface);
interfaze.addsuperinterface(fqjt);
interfaze.addimportedtype(fqjt);
}

addinsertselectivemethod(interfaze);
adddeletebyprimarykeymethod(interfaze);
adddeletebyexamplemethod(interfaze);
addupdatebyprimarykeyselectivemethod(interfaze);
addupdatebyexampleselectivemethod(interfaze);
addselectbyprimarykeymethod(interfaze);
addselectonebyexamplemethod(interfaze); //由addselectbyexamplewithoutblobsmethod改造而来
addselectbyexamplewithoutblobsmethod(interfaze);
addselectbyexamplewithblobsmethod(interfaze);
addcountbyexamplemethod(interfaze);
//addinsertmethod(interfaze);
//addupdatebyexamplewithblobsmethod(interfaze);
//addupdatebyexamplewithoutblobsmethod(interfaze);
//addupdatebyprimarykeywithblobsmethod(interfaze);
//addupdatebyprimarykeywithoutblobsmethod(interfaze);

list<compilationunit> answer = new arraylist<>();
if (context.getplugins().clientgenerated(interfaze, null,
introspectedtable)) {
answer.add(interfaze);
}

list<compilationunit> extracompilationunits = getextracompilationunits();
if (extracompilationunits != null) {
answer.addall(extracompilationunits);
}

return answer;
}

//增加方法
protected void addselectonebyexamplemethod(interface interfaze) {   abstractjavamappermethodgenerator methodgenerator = new selectonebyexamplemethodgenerator();   initializeandexecutegenerator(methodgenerator, interfaze); }

 同样地,修改xmlmappergenerator

protected xmlelement getsqlmapelement() {
        fullyqualifiedtable table = introspectedtable.getfullyqualifiedtable();
        progresscallback.starttask(getstring(
                "progress.12", table.tostring())); //$non-nls-1$
        xmlelement answer = new xmlelement("mapper"); //$non-nls-1$
        string namespace = introspectedtable.getmybatis3sqlmapnamespace();
        answer.addattribute(new attribute("namespace", //$non-nls-1$
                namespace));

        context.getcommentgenerator().addrootcomment(answer);

        addresultmapwithoutblobselement(answer);
        addresultmapwithblobselement(answer);
        addexamplewhereclauseelement(answer);
        addmybatis3updatebyexamplewhereclauseelement(answer);
        addbasecolumnlistelement(answer);
        addblobcolumnlistelement(answer);
        addinsertselectiveelement(answer);
        adddeletebyprimarykeyelement(answer);
        adddeletebyexampleelement(answer);
        addupdatebyprimarykeyselectiveelement(answer);
        addupdatebyexampleselectiveelement(answer);
        addselectbyprimarykeyelement(answer);
        addselectonebyexampleelement(answer);
        addselectbyexamplewithoutblobselement(answer);
        addselectbyexamplewithblobselement(answer);
        addcountbyexampleelement(answer);
        //addselectbyexamplewithblobselement(answer);
        //addinsertelement(answer);
        //addupdatebyexamplewithblobselement(answer);
        //addupdatebyexamplewithoutblobselement(answer);
        //addupdatebyprimarykeywithblobselement(answer);
        //addupdatebyprimarykeywithoutblobselement(answer);

        return answer;
}

//增加方法 protected void addselectonebyexampleelement(xmlelement parentelement) {   if (introspectedtable.getrules().generateselectbyexamplewithoutblobs()) {     abstractxmlelementgenerator elementgenerator = new selectonebyexampleelementgenerator();     initializeandexecutegenerator(elementgenerator, parentelement);   } }

投入使用

deploy项目打包,然后在需要使用的项目中,修改pom.xml引入,再使用generator的generate命令即可

       <plugin>
                <groupid>org.mybatis.generator</groupid>
                <artifactid>mybatis-generator-maven-plugin</artifactid>
                <version>1.3.7</version>
                <dependencies>
                    <dependency>
                        <groupid>com.mine.generator</groupid>
                        <artifactid>mybatis-generator-core</artifactid>
                        <version>1.0-snapshot</version>
                    </dependency>
                </dependencies>
            </plugin>