使用mybatis-generator生成自动代码

时间:2021-04-21 05:10:22

2019-02-22

配置文件:

pom.xml  添加 dependency plugin    基于mybatis-plus

使用mybatis-generator生成自动代码使用mybatis-generator生成自动代码
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.6</version>
            <scope>compile</scope>
        </dependency>
View Code
使用mybatis-generator生成自动代码使用mybatis-generator生成自动代码
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.6</version>
                <configuration>
                    <!--配置文件的位置-->
                    <configurationFile>generator.xml</configurationFile>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
                <executions>
                    <execution>
                        <id>Generate MyBatis Artifacts</id>
                        <phase>deploy</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.6</version>
                    </dependency>
                    <dependency>
                        <groupId>com.oracle</groupId>
                        <artifactId>ojdbc6</artifactId>
                        <version>11.2.0.3</version>
                    </dependency>
                    <dependency>
                        <groupId>org.mybatis</groupId>
                        <artifactId>mybatis</artifactId>
                        <version>3.4.6</version>
                    </dependency>

                    <dependency>
                        <groupId>my.base.project</groupId>
                        <artifactId>base-core</artifactId>
                        <version>1.0-SNAPSHOT</version>
                    </dependency>

                </dependencies>
            </plugin>
View Code

generatorConfiguration.xml

使用mybatis-generator生成自动代码使用mybatis-generator生成自动代码
<?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.properties" />

    <context id="default" targetRuntime="MyBatis3">
        <!-- 生成的Java文件的编码 -->
        <property name="javaFileEncoding" value="UTF-8" />
        <!-- 格式化java代码 -->
        <property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter" />

        <!-- 使用自定义的插件 -->
        <!-- 整合lombok -->
        <plugin type="*.support.GeneratorPlugin"/>

        <commentGenerator>
            <!--  关闭自动生成的注释  -->
            <property name="suppressAllComments" value="true"/>
            <!--生成的注释包含时间戳-->
            <property name="suppressDate" value="true"/>
        </commentGenerator>

        <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="${jdbc.driver}"
                        connectionURL="${jdbc.url}"
                        userId="${jdbc.username}"
                        password="${jdbc.password}">
            <!-- 字段注解 针对oracle数据库 -->
            <property name="remarksReporting" value="true" />
            <!-- 字段注解 针对mysql数据库 -->
            <property name="useInformationSchema" value="true"/>
        </jdbcConnection>

        <!-- 类型转换 -->
        <javaTypeResolver>
            <!-- 是否使用bigDecimal
                默认false:把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,
                为 true时:把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal
            -->
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- 生成实体类 -->
        <!-- targetPackage:生成实体类的包名 -->
        <!-- targetProject:生成PO类的位置 -->
        <javaModelGenerator targetPackage="${model.package}"
                            targetProject="${target.project}/java">
            <!--所有实体类继承BasePojo类-->
            <property name="rootClass" value="*.base.BaseModel"/>
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="false"/>
        </javaModelGenerator>

        <!-- 生成XxxMapper.xml文件 -->
        <!-- targetProject:mapper映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="${xml.mapper.package}"
                         targetProject="${target.project}/resources">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!-- 生成XxxMapper.java文件 -->
        <!--ANNOTATEDMAPPER: 生成java类文件,基于注解的Mapper接口,不会有对应的XML映射文件
            MIXEDMAPPER:XML和注解的混合形式
            XMLMAPPER:所有的方法都在XML中,接口调用依赖XML文件 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="${mapper.package}"
                             targetProject="${target.project}/java">
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>

        <table schema="JTP"
               tableName="${table.name}"
               domainObjectName="${table.domainObjectName}"

               enableSelectByPrimaryKey="true"

               enableInsert="false"
               enableUpdateByPrimaryKey="false"
               enableDeleteByPrimaryKey="false"

               enableSelectByExample="false"
               enableUpdateByExample="false"
               enableDeleteByExample="false"
               enableCountByExample="false"
               selectByExampleQueryId="false">
        </table>
    </context>
</generatorConfiguration>
View Code

generator.properties  config 使用的参数

使用mybatis-generator生成自动代码使用mybatis-generator生成自动代码
# 数据库连接配置
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@ip:orcl
jdbc.username=name
jdbc.password=password


# 文件路径配置
model.package=*.model.menu
mapper.package=*.mapper
xml.mapper.package=mapper.db
target.project=src/main

# 执行的表数据
table.name=SYS_MENU_T
table.domainObjectName=Menu
View Code

 

自定义插件文件:

GeneratorPlugin.java  Model自定义注释,Inteface 自定义基类,xml删除多余方法 支持lombok插件

使用mybatis-generator生成自动代码使用mybatis-generator生成自动代码
import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.GeneratedXmlFile;
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 org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.Element;

import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;


/**
 * Mybatis 代码生成自定义插件
 * A MyBatis Generator plugin to use Lombok's annotations.
 * For example, use @Data annotation instead of getter ands setter.
 *
 * @className GeneratorPlugin
 * @author joe
 * @version V1.0.0
 * @date 2019-01-16
*/
public class GeneratorPlugin extends PluginAdapter {

    private final Collection<Annotations> annotations;

    /**
     * GeneratorPlugin constructor
     */
    public GeneratorPlugin() {
        annotations = new LinkedHashSet<>(Annotations.values().length);
    }

    /**
     * @param warnings list of warnings
     * @return always true
     */
    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }

    /**
     * Intercepts base record class generation
     *
     * @param topLevelClass     the generated base record class
     * @param introspectedTable The class containing information about the table as
     *                          introspected from the database
     * @return always true
     */
    @Override
    public boolean modelBaseRecordClassGenerated(
            TopLevelClass topLevelClass,
            IntrospectedTable introspectedTable
    ) {
        addModelClassComment(topLevelClass, introspectedTable);
        return true;
    }

    /**
     * Intercepts primary key class generation
     *
     * @param topLevelClass     the generated primary key class
     * @param introspectedTable The class containing information about the table as
     *                          introspected from the database
     * @return always true
     */
    @Override
    public boolean modelPrimaryKeyClassGenerated(
            TopLevelClass topLevelClass,
            IntrospectedTable introspectedTable
    ) {
        addModelClassComment(topLevelClass, introspectedTable);
        return true;
    }

    /**
     * Intercepts "record with blob" class generation
     *
     * @param topLevelClass     the generated record with BLOBs class
     * @param introspectedTable The class containing information about the table as
     *                          introspected from the database
     * @return always true
     */
    @Override
    public boolean modelRecordWithBLOBsClassGenerated(
            TopLevelClass topLevelClass,
            IntrospectedTable introspectedTable
    ) {
        addModelClassComment(topLevelClass, introspectedTable);
        return true;
    }

    /**
     * 类属性注释
     *
     * @param field 属性
     * @param topLevelClass 类对象
     * @param introspectedColumn 列
     * @param introspectedTable 表
     * @param modelClassType Class类型
     * @return true
     */
    @Override
    public boolean modelFieldGenerated(Field field,
                                       TopLevelClass topLevelClass,
                                       IntrospectedColumn introspectedColumn,
                                       IntrospectedTable introspectedTable,
                                       ModelClassType modelClassType) {
        StringBuilder sb = new StringBuilder();
        field.addJavaDocLine("/**");
        sb.append(" * ");
        // 字段注释
        sb.append(columnRemarks(introspectedColumn.getRemarks()));
        field.addJavaDocLine(sb.toString().replace("\n", " "));
        field.addJavaDocLine(" */");

        // 主键
        if (introspectedTable.getPrimaryKeyColumns().stream()
                .anyMatch(p -> p.equals(introspectedColumn))) {
            field.addAnnotation("@TableId");
        }

        // 字段上生成@TableField注解
        field.addAnnotation("@TableField(value = \"" + introspectedColumn.getActualColumnName() + "\")");
        return true;
    }

    /**
     * Prevents all getters from being generated.
     * See SimpleModelGenerator
     *
     * @param method             the getter, or accessor, method generated for the specified
     *                           column
     * @param topLevelClass      the partially implemented model class
     * @param introspectedColumn The class containing information about the column related
     *                           to this field as introspected from the database
     * @param introspectedTable  The class containing information about the table as
     *                           introspected from the database
     * @param modelClassType     the type of class that the field is generated for
     */
    @Override
    public boolean modelGetterMethodGenerated(
            Method method,
            TopLevelClass topLevelClass,
            IntrospectedColumn introspectedColumn,
            IntrospectedTable introspectedTable,
            ModelClassType modelClassType
    ) {
        return false;
    }

    /**
     * Prevents all setters from being generated
     * See SimpleModelGenerator
     *
     * @param method             the setter, or mutator, method generated for the specified
     *                           column
     * @param topLevelClass      the partially implemented model class
     * @param introspectedColumn The class containing information about the column related
     *                           to this field as introspected from the database
     * @param introspectedTable  The class containing information about the table as
     *                           introspected from the database
     * @param modelClassType     the type of class that the field is generated for
     * @return always false
     */
    @Override
    public boolean modelSetterMethodGenerated(
            Method method,
            TopLevelClass topLevelClass,
            IntrospectedColumn introspectedColumn,
            IntrospectedTable introspectedTable,
            ModelClassType modelClassType
    ) {
        return false;
    }

    /**
     * 增加类注释
     *
     * @param topLevelClass 类
     * @param introspectedTable 表数据
     */
    private void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {

        topLevelClass.addJavaDocLine("/**");
        topLevelClass.addJavaDocLine(" * " + tableRemarks(introspectedTable));
        topLevelClass.addJavaDocLine(" * ");
        topLevelClass.addJavaDocLine(" * @author " + System.getProperty("user.name"));
        topLevelClass.addJavaDocLine(" * @date " + new Date().toString());
        topLevelClass.addJavaDocLine(" *");
        topLevelClass.addJavaDocLine(" */");

        addAnnotations(topLevelClass);

        topLevelClass.addImportedType("com.baomidou.mybatisplus.annotation.TableField");
        topLevelClass.addImportedType("com.baomidou.mybatisplus.annotation.TableId");
        topLevelClass.addImportedType("com.baomidou.mybatisplus.annotation.TableName");

        // 添加类注解
        // 表名
        String tableName = introspectedTable.getFullyQualifiedTable().getIntrospectedTableName();
        topLevelClass.addAnnotation(String.format("@TableName(\"%s\")", tableName));
    }

    /**
     * Adds the lombok annotations' imports and annotations to the class
     *
     * @param topLevelClass the partially implemented model class
     */
    private void addAnnotations(TopLevelClass topLevelClass) {
        //@Data is default annotation
        annotations.add(Annotations.DATA);
        annotations.add(Annotations.EQUALS);

        for (Annotations annotation : annotations) {
            topLevelClass.addImportedType(annotation.javaType);
            topLevelClass.addAnnotation(annotation.name);
        }
    }

    /**
     * 数据字典类型 mapper
     */
    @Override
    public boolean clientGenerated(
            Interface interfaze,
            TopLevelClass topLevelClass,
            IntrospectedTable introspectedTable
    ) {

        interfaze.addJavaDocLine("/**");
        interfaze.addJavaDocLine(" * " + tableRemarks(introspectedTable) + " Mapper");
        interfaze.addJavaDocLine(" * ");
        interfaze.addJavaDocLine(" * @author " + System.getProperty("user.name"));
        interfaze.addJavaDocLine(" * @date " + new Date().toString());
        interfaze.addJavaDocLine(" *");
        interfaze.addJavaDocLine(" */");

        interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Mapper"));
        interfaze.addAnnotation("@Mapper");

        interfaze.addImportedType(new FullyQualifiedJavaType("com.baomidou.mybatisplus.core.mapper.BaseMapper"));

        FullyQualifiedJavaType superMapper =
                new FullyQualifiedJavaType(String.format("BaseMapper<%s>", introspectedTable.getBaseRecordType()));

        // 添加 extends MybatisPlusBaseMapper
        interfaze.addSuperInterface(superMapper);

        // 清理方法
        interfaze.getMethods().clear();

        return true;
    }

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        // 设置 xml文件时覆盖写  默认:true [mybatis generator默认采用追加方式生成]
        sqlMap.setMergeable(false);
        return super.sqlMapGenerated(sqlMap, introspectedTable);
    }

    @Override
    public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
        // 之前 table 配置 保留了 一个SelectByPrimaryKey 设置为true 此处删除
        List<Element> list = document.getRootElement().getElements();
        list.remove(list.size() - 1);
        return true;
    }

    private String tableRemarks(IntrospectedTable introspectedTable) {
        String remark = introspectedTable.getRemarks();
        if (StringUtils.isEmpty(remark)) {
            return introspectedTable.getFullyQualifiedTable().getIntrospectedTableName();
        }
        return remark;
    }

    private String columnRemarks(String remark) {
        if (StringUtils.isEmpty(remark)) {
            return "TODO add remark";
        }
        return remark;
    }

    /**
     * Lombok 相关的注解
     *
     * @className Annotations
     * @author joe
     * @version V1.0.0
     * @date 2019-02-21 10:35
    */
    private enum Annotations {
        /**
         * data
         */
        DATA("data", "@Data", "lombok.Data"),
        BUILDER("builder", "@Builder", "lombok.Builder"),
        EQUALS("equalsAndHashCode", "@EqualsAndHashCode(callSuper = false)", "lombok.EqualsAndHashCode"),
        ALL_ARGS_CONSTRUCTOR("allArgsConstructor", "@AllArgsConstructor", "lombok.AllArgsConstructor"),
        NO_ARGS_CONSTRUCTOR("noArgsConstructor", "@NoArgsConstructor", "lombok.NoArgsConstructor"),
        ACCESSORS("accessors", "@Accessors", "lombok.experimental.Accessors"),
        TO_STRING("toString", "@ToString", "lombok.ToString");

        private final String paramName;
        private final String name;
        private final FullyQualifiedJavaType javaType;

        Annotations(String paramName, String name, String className) {
            this.paramName = paramName;
            this.name = name;
            this.javaType = new FullyQualifiedJavaType(className);
        }

    }
}
View Code

 

使用方式:

mvn mybatis-generator:generate

如果是在intellij 环境,直接鼠标点击即可

使用mybatis-generator生成自动代码

 

 生成效果:

使用mybatis-generator生成自动代码使用mybatis-generator生成自动代码
import *.base.BaseModel;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * 系统菜单
 * 
 * @author joe
 * @date 2019-01-20
 *
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("SYS_MENU_T")
public class Menu extends BaseModel {
    /**
     * 菜单ID
     */
    @TableId
    @TableField(value = "MENU_ID")
    private String menuId;

    /**
     * 菜单编码,不允许重复
     */
    @TableField(value = "MENU_CODE")
    private String menuCode;

    /**
     * 菜单名称,同一个级别下不允许重复
     */
    @TableField(value = "MENU_NAME")
    private String menuName;
}
View Code
使用mybatis-generator生成自动代码使用mybatis-generator生成自动代码
import *.MenuEO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

/**
 * 系统菜单 Mapper
 * 
 * @author joe
 * @date 2019-01-22 16:24
 *
 */
@Mapper
public interface MenuMapper extends BaseMapper<Menu> {
}
View Code
使用mybatis-generator生成自动代码使用mybatis-generator生成自动代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="*.mapper.MenuMapper">
  <resultMap id="BaseResultMap" type="*.Menu">
    <id column="MENU_ID" jdbcType="VARCHAR" property="menuId" />
    <result column="MENU_CODE" jdbcType="VARCHAR" property="menuCode" />
    <result column="MENU_NAME" jdbcType="VARCHAR" property="menuName" />
  </resultMap>
  <sql id="Base_Column_List">
    MENU_ID, MENU_CODE, MENU_NAME
  </sql>
</mapper>
View Code

 

常见问题:

1、运行报错,找不到自定义的插件类[generate failed: Cannot instantiate object of type *.MyPlugin]

原因:mybatis-generator 的plugin有自己的classpath,我们在项目中直接继承的类和plugin不属于同一个classpath

解决:把插件类打基础包,再pom的plugin配置中被 mybatis-generator 的plugin 依赖。

2、报错[There are no statements enabled for table mybatis.category, this table will be ignored.]

原因:generatorConfig.xml中,<table>标签配成 所有原始的sql都是false

使用mybatis-generator生成自动代码

解决:保留一个时true的设置,再插件中处理xml时再删除。

3、获取不到数据库字段的注释

原因:mysql 和 oracle的数据库配置不同,确认配置

解决:在generatorConfiguration.xml配置文件中配置

使用mybatis-generator生成自动代码使用mybatis-generator生成自动代码
        <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="${jdbc.driver}"
                        connectionURL="${jdbc.url}"
                        userId="${jdbc.username}"
                        password="${jdbc.password}">
            <!-- 字段注解 针对oracle数据库 -->
            <property name="remarksReporting" value="true" />
            <!-- 字段注解 针对mysql数据库 -->
            <property name="useInformationSchema" value="true"/>
        </jdbcConnection>
View Code

4、xml文件再次生成时被追加

原因:mybatis generator默认采用追加方式生成

解决:重写sqlMapGenerated方法。设置sqlMap.setMergeable(false);。默认情况下isMergeable为true,所以在这里设置为false。

 

mybatis-generator.xml配置文件详解 参考 https://blog.csdn.net/weixin_39805338/article/details/80999186