zoukankan      html  css  js  c++  java
  • mybatis-generator:自定义插件之分页、序列化、集成lombok

    0.需求

    在我们使用mybatis-generator的过程中,往往其自带的功能不能够满足我们的需求。

    此时我们就需要进行插件开发了。

    1.准备工作

    新建一个Maven项目,引入依赖 mybatis-generator-core

    2.开发分页

    在mysql中,我们一般使用limit来实现分页

    之前的做法是在mybatis-generator生成完成之后手动在Example中两个属性,offset,rows

    然后在xml中添加条件判断,追加limit。

    这里我们就通过这个思路在开发分页插件。

    import org.mybatis.generator.api.IntrospectedTable;
    import org.mybatis.generator.api.PluginAdapter;
    import org.mybatis.generator.api.dom.java.*;
    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 java.util.List;
    
    public class LimitPlugin extends PluginAdapter {
    
        @Override
        public boolean validate(List<String> list) {
            return true;
        }
    
        /**
         * 为每个Example类添加offset和rows属性已经set、get方法
         */
        @Override
        public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    
            PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper();
    
            Field rows = new Field();
            rows.setName("rows");
            rows.setVisibility(JavaVisibility.PRIVATE);
            rows.setType(integerWrapper);
            topLevelClass.addField(rows);
    
            Method setRows = new Method();
            setRows.setVisibility(JavaVisibility.PUBLIC);
            setRows.setName("setRows");
            setRows.addParameter(new Parameter(integerWrapper, "rows"));
            setRows.addBodyLine("this.rows = rows;");
            topLevelClass.addMethod(setRows);
    
            Method getRows = new Method();
            getRows.setVisibility(JavaVisibility.PUBLIC);
            getRows.setReturnType(integerWrapper);
            getRows.setName("getRows");
            getRows.addBodyLine("return rows;");
            topLevelClass.addMethod(getRows);
    
            Field offset = new Field();
            offset.setName("offset");
            offset.setVisibility(JavaVisibility.PRIVATE);
            offset.setType(integerWrapper);
            topLevelClass.addField(offset);
    
            Method setOffset = new Method();
            setOffset.setVisibility(JavaVisibility.PUBLIC);
            setOffset.setName("setOffset");
            setOffset.addParameter(new Parameter(integerWrapper, "offset"));
            setOffset.addBodyLine("this.offset = offset;");
            topLevelClass.addMethod(setOffset);
    
            Method getOffset = new Method();
            getOffset.setVisibility(JavaVisibility.PUBLIC);
            getOffset.setReturnType(integerWrapper);
            getOffset.setName("getOffset");
            getOffset.addBodyLine("return offset;");
            topLevelClass.addMethod(getOffset);
    
            return true;
        }
    
        /**
         * 为Mapper.xml的selectByExample添加limit
         */
        @Override
        public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
    
            XmlElement ifLimitNotNullElement = new XmlElement("if");
            ifLimitNotNullElement.addAttribute(new Attribute("test", "rows != null"));
    
            XmlElement ifOffsetNotNullElement = new XmlElement("if");
            ifOffsetNotNullElement.addAttribute(new Attribute("test", "offset != null"));
            ifOffsetNotNullElement.addElement(new TextElement("limit ${offset}, ${rows}"));
            ifLimitNotNullElement.addElement(ifOffsetNotNullElement);
    
            XmlElement ifOffsetNullElement = new XmlElement("if");
            ifOffsetNullElement.addAttribute(new Attribute("test", "offset == null"));
            ifOffsetNullElement.addElement(new TextElement("limit ${rows}"));
            ifLimitNotNullElement.addElement(ifOffsetNullElement);
    
            element.addElement(ifLimitNotNullElement);
    
            return true;
        }
    }

    3.集成Lombok、序列化

    使用lombok可以使代码更简洁

    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.*;
    
    import java.util.List;
    
    public class LombokPlugin extends PluginAdapter {
        @Override
        public boolean validate(List<String> warnings) {
    
            return true;
        }
    
        @Override
        public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    
            // 添加domain的import
            topLevelClass.addImportedType("lombok.Data");
            topLevelClass.addImportedType("lombok.NoArgsConstructor");
            topLevelClass.addImportedType("lombok.AllArgsConstructor");
            topLevelClass.addImportedType("java.io.Serializable");
    
            // 添加domain的注解
            topLevelClass.addAnnotation("@Data");
            topLevelClass.addAnnotation("@NoArgsConstructor");
            topLevelClass.addAnnotation("@AllArgsConstructor");
    
            // 序列化
            generatorDefaultSerialVersionUID(topLevelClass);
    
            return true;
        }
    
        // 不生成getter
        @Override
        public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass,
                                                  IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
    
            return false;
        }
    
        // 不生成setter
        @Override
        public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass,
                                                  IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
    
            return false;
        }
    
        /**
         * 序列化
         *
         * @param topLevelClass
         */
        private void generatorDefaultSerialVersionUID(TopLevelClass topLevelClass) {
            FullyQualifiedJavaType serializable = new FullyQualifiedJavaType("java.io.Serializable");
            topLevelClass.addSuperInterface(serializable);
    
            Field field = new Field();
            field.setFinal(true);
            field.setInitializationString("1L");
            field.setName("serialVersionUID");
            field.setStatic(true);
            field.setType(new FullyQualifiedJavaType("long"));
            field.setVisibility(JavaVisibility.PRIVATE);
            topLevelClass.getFields().add(0, field);
        }
    }

    4.使用运行

    到这里我们就将两个自定义的插件开发完成了。

    这里建议是将这两个插件放在一个单独的项目,一是为了方便复用,另一个是我放在同一个项目下的时候,运行好像有点问题。

    4.1.打包插件

    通过mvn install将我们的插件进行打包,打包为jar包,方便后续使用。

    4.2.使用插件

    <plugin>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <configuration>
            <configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile>
            <overwrite>true</overwrite>
        </configuration>
        <dependencies>
            <dependency>
                <groupId>com.xxxx</groupId>
                <artifactId>xxxx</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </plugin>

    更改pom.xml,在mybatis-generator的maven插件中引入我们刚刚的项目

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
            PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
            "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    <generatorConfiguration>
    
        <!--导入属性配置 -->
        <properties resource="generator/generator.properties"></properties>
    
        <!--指定特定数据库的jdbc驱动jar包的位置
            location:
                The full path name of a JAR/ZIP file to add to the classpath,
                or a directory to add to the classpath.
        -->
        <classPathEntry location="${jdbc.driverLocation}"/>
    
        <context id="default" targetRuntime="Mybatis3">
    
            <!--使用``包裹mysql关键字-->
            <property name="autoDelimitKeywords" value="true"/>
            <property name="beginningDelimiter" value="`"/>
            <property name="endingDelimiter" value="`"/>
    
            <plugin type="com.fdzang.formybatis.config.LombokPlugin"/>
            <plugin type="com.fdzang.formybatis.config.LimitPlugin"/>
    
            <!-- optional,旨在创建class时,去掉注释 -->
            <commentGenerator>
                <property name="suppressDate" value="false"/>
                <property name="suppressAllComments" value="true"/>
            </commentGenerator>
    
            <jdbcConnection driverClass="${jdbc.driver}"
                            connectionURL="${jdbc.url}"
                            userId="${jdbc.username}"
                            password="${jdbc.password}">
            </jdbcConnection>
    
            <!-- 非必需,类型处理器,在数据库类型和java类型之间的转换控制-->
            <javaTypeResolver >
                <property name="forceBigDecimals" value="false" />
            </javaTypeResolver>
    
            <!--配置实体bean-->
            <javaModelGenerator targetPackage="com.fdzang.microservice.blog.article.dao.domain"
                                targetProject="src/main/java">
                <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
                <property name="enableSubPackages" value="false"/>
                <!-- 是否对类CHAR类型的列的数据进行trim操作 -->
                <property name="trimStrings" value="false"/>
            </javaModelGenerator>
    
            <!-- 配置实体bean的mapper.xml-->
            <sqlMapGenerator targetPackage="mapper"
                             targetProject="src/main/resources">
                <property name="enableSubPackages" value="true"/>
            </sqlMapGenerator>
    
            <!-- 配置实体mapper接口-->
            <javaClientGenerator targetPackage="com.fdzang.microservice.blog.article.dao.mapper"
                                 targetProject="src/main/java"
                                 type="XMLMAPPER">
                <property name="enableSubPackages" value="true"/>
            </javaClientGenerator>
    
            <table tableName="test"
                   domainObjectName="TestDO"
                   mapperName="TestMapper"
                   enableInsert="true"
                   enableUpdateByPrimaryKey="true"
                   enableDeleteByPrimaryKey="true"
                   enableCountByExample="false"
                   enableUpdateByExample="false"
                   enableDeleteByExample="false"
                   enableSelectByExample="true"
                   selectByExampleQueryId="false">
            </table>
    
        </context>
    </generatorConfiguration>

    修改generatorConfig.xml,在<context>中引入插件<plugin>,这里有个注意事项是,plugin放置的顺序,需要在<property>下

    4.3.运行效果

    import java.io.Serializable;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    import lombok.NoArgsConstructor;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @EqualsAndHashCode(callSuper = false)
    public class TestDO implements Serializable {
        private static final long serialVersionUID = 1L;
    
        private Integer id;
    
        private String test;
    }

    Example,去掉了其他部分。

    public class TestDOExample {
        private Integer rows;
    
        private Integer offset;
    
        public TestDOExample() {
            oredCriteria = new ArrayList<Criteria>();
        }
        
        public void setRows(Integer rows) {
            this.rows = rows;
        }
    
        public Integer getRows() {
            return rows;
        }
    
        public void setOffset(Integer offset) {
            this.offset = offset;
        }
    
        public Integer getOffset() {
            return offset;
        }
    }

    Mapper

    <select id="selectByExample" parameterType="com.fdzang.microservice.blog.article.dao.domain.TestDOExample" resultMap="BaseResultMap">
      select
      <if test="distinct">
        distinct
      </if>
      'false' as QUERYID,
      <include refid="Base_Column_List" />
      from test
      <if test="_parameter != null">
        <include refid="Example_Where_Clause" />
      </if>
      <if test="orderByClause != null">
        order by ${orderByClause}
      </if>
      <if test="rows != null">
        <if test="offset != null">
          limit ${offset}, ${rows}
        </if>
        <if test="offset == null">
          limit ${rows}
        </if>
      </if>
    </select>

    5.其他

    其实自定义mybatis-generator的插件,主要是通过继承PluginAdapter来实现的。

    PluginAdapter中还有很多其他的方法,可以进行自定义修改,大家可以根据需要进行自定义改造。

    参考:

    http://xxgblog.com/2016/05/06/mybatis-generator-mysql-pagination/

    https://www.jianshu.com/p/b243f3ec8419

  • 相关阅读:
    进程间通信(一):竞争条件与相互排斥方案
    (素材源代码) 猫猫学iOS 之UIDynamic重力、弹性碰撞吸附等现象牛逼Demo
    <html>
    模运算的规则
    ubuntu16.04重置root密码
    rancheros在vm主机部署
    基于centos7.6离线部署开k3s
    centos7.6在线yum安装docker-ce
    centos在线安装ffmpeg
    tar.bz2解压异常
  • 原文地址:https://www.cnblogs.com/fdzang/p/12843687.html
Copyright © 2011-2022 走看看