mybatis plus generator 3.5.1 从了解到自定义定制VO、PO、DTO

2023-05-16

一、背景说明:

在项目研发过程中,通过自动化工具生成ORM对象关系映射是一件必不可少的工作。

mybatis plus generator 是一个很好用的工具,在新搭建的项目中研发兄弟尝新,使用了 generator 的3.5.1 和3.5.2 版本,在生成自带的基础工具类的基础上,想再同时生成相应的 PO、VO、DTO和转换工具等实体,发现3.5.1以上关于自定义定制类资料较少,因故写此文章,记录研学结果。希望对大家有用

二、mybatis plus generator jar 包引入

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>3.5.1</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.1</version>
</dependency>

三、开发环境简单介绍

mac 、jdk 1.8 、idea 、mysql 、使用 Velocity 模板自定义生成工具类(默认)

四、基础配置使用说明

1、基础路径信息配置


/**数据库链接地址**/
private static final String JDBC_URL_MAN = "jdbc:mysql://127.0.0.1:3306/myDatabase?useUnicode=true&characterEncoding=UTF-8";
/**数据库登录账号**/
private static final String JDBC_UserName = "root";
/**数据库登录密码**/
private static final String JDBC_Password = "root1234";
/**
 * 【需要修改】
 * 需要进行生成文件的表名
 *          多张表,表名间使用,号分割
 **/
private static final String[] Tables = { "user_table"};

/**
 * 【需要修改】
 * 生成类的注释
 * 作者名称
 */
private static final String CODE_AUTHOR = "timerbin";

/**
 * 生成的文件存放地址 之
 *      文件路径
 */
private static final String FILE_STORAGE_FILE_ROOT_PATH = System.getProperty("user.dir")+"/user-obj/user-obj-dao/src/test/java/";
/**
 *  生成的文件存放地址 之
 *      父级 jar包路径
 */
private static final String FILE_STORAGE_FILE_JAR_PACKAGE = "com.jd.timer.bin.user.dao";
/**
 *
 *  生成的文件存放地址 之
 *      模块 jar包名称
 */
private static final String FILE_STORAGE_FILE_JAR_PACKAGE_MODULE = "build";
/**
 *  生成的文件存放地址 之
 *      Service 接口 存放地址
 */
private static final String FILE_STORAGE_SERVICE_FILE_JAR_PACKAGE= "service";
/**
 *  生成的文件存放地址 之
 *      Service impl 实现类 存放地址
 */
private static final String FILE_STORAGE_SERVICE_IMPL_FILE_JAR_PACKAGE= "impl";

/**
 *  生成的文件存放地址 之
 *      entity  实体类 存放地址
 */
private static final String FILE_STORAGE_ENTITY_FILE_JAR_PACKAGE= "entity";

/**
 *  生成的文件存放地址 之
 *      mapper  操作类 存放地址
 */
private static final String FILE_STORAGE_MAPPER_FILE_JAR_PACKAGE= "mapper";


/**
 *  生成的文件存放地址 之
 *      mapper  xml 文件 存放地址
 */
private static final String FILE_STORAGE_MAPPER_XML_FILE_JAR_PACKAGE= "mapper";


/**
 *  自定义 、定制 生成的文件存放地址 之
 *      other 其他文件 存放地址
 */
private static final String FILE_STORAGE_OTHER_FILE_JAR_PACKAGE= "other";

以上配置主要目的是指定数据库、表,以及生成的基础文件存放路径,此处无需多关注,且朝下看

2、自动生成工具 main 方法

public static void main(String[] args) {

    //设置数据库信息
    /***
     * 数据库信息配置
     */
    DataSourceConfig dataSourceConfig = configDataSource();
    /**
     * 生成工具类
     **/
    AutoGenerator generator = new AutoGenerator(dataSourceConfig);
    /**
     * 全局变量配置
     */
    generator.global(configGlobel());
    /**
     * 设置生成文件包名地址
     */
    generator.packageInfo(configPackage());

    /**
     * 生成文件的策略配置
     */
    generator.strategy(configStratgy());

    /**
     * 生成的类的模板配置
     */
    generator.template(configTemplate());

    /**
     * 自定义实体信息
     **/
    generator.injection(initInjectionConfig());

    /**
     * 自定义模板解析器
     */
    YaoVelocityTemplateEngine yaoVelocityTemplateEngine = new YaoVelocityTemplateEngine();

    generator.execute(yaoVelocityTemplateEngine);

}

相关jar 包引用

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.IFill;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.fill.Column;
import com.baomidou.mybatisplus.generator.keywords.MySqlKeyWordsHandler;

3、关键各个子方法

/**
 * 配置基础转换器
 * @return
 */
private static DataSourceConfig configDataSource() {
    /**数据库链接配置**/
    DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(
            JDBC_URL_MAN,
            JDBC_UserName,
            JDBC_Password
    )
            .dbQuery(new MySqlQuery())
            /**自定义转换器,将tinyint 转换为Integer**/
            .typeConvert(new EasyMySqlTypeConvert())
            .keyWordsHandler(new MySqlKeyWordsHandler())
            .build();

    return dataSourceConfig;
}

/**
 * 自定义转换器转换器 内部类
 *         目的将数据库表中定义的  tinyint 或 bit类型转变为 java Integer 类型
 * @author timerbin
 */
 static class EasyMySqlTypeConvert extends MySqlTypeConvert {
    @Override
    public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {
        IColumnType iColumnType = super.processTypeConvert(config, fieldType);
        if (fieldType.equals("tinyint(1)")) {
            iColumnType = DbColumnType.INTEGER;
        }
        if (fieldType.equals("bit(1)")) {
            iColumnType = DbColumnType.BYTE;
        }
        return iColumnType;
    }
}

/**
 * 设置全局变量
 * @return
 */
private static GlobalConfig configGlobel() {

    GlobalConfig globalConfig = new GlobalConfig.Builder()
            .fileOverride()
            .disableOpenDir()
            /**存放生成文件的文件夹地址**/
            .outputDir(FILE_STORAGE_FILE_ROOT_PATH)
            .author(CODE_AUTHOR)
            .dateType(DateType.ONLY_DATE)
            .commentDate("yyyy-MM-dd hh:mm:ss")
            .build();
    return globalConfig;
}

/**
 * 生成文件存储目录配置
 * @return
 */
private static PackageConfig configPackage() {
    PackageConfig packageConfig = new PackageConfig.Builder()
            /**存放生成文件的 父级 package 地址**/
            .parent(FILE_STORAGE_FILE_JAR_PACKAGE)
            /**存放生成文件的 的 父级模块地址**/
            .moduleName(FILE_STORAGE_FILE_JAR_PACKAGE_MODULE)
            /**存放生成文件的 service 接口 存放的package地址**/
            .service(FILE_STORAGE_SERVICE_FILE_JAR_PACKAGE)
            /**存放生成文件的 service 接口实现类 存放的package地址**/
            .serviceImpl(FILE_STORAGE_SERVICE_IMPL_FILE_JAR_PACKAGE)
            /**存放生成文件的 实体类 存放的package地址**/
            .entity(FILE_STORAGE_ENTITY_FILE_JAR_PACKAGE)
            /**存放生成文件的 mapper 操作类 存放的package地址**/
            .mapper(FILE_STORAGE_MAPPER_FILE_JAR_PACKAGE)
            /**存放生成文件的 mapper 操作类 xml 存放的package地址**/
            .xml(FILE_STORAGE_MAPPER_XML_FILE_JAR_PACKAGE)
            /**存放生成文件的 其他实体类 存放的package地址**/
            .other(FILE_STORAGE_OTHER_FILE_JAR_PACKAGE)
            .build();
    return packageConfig;
}

/**
 * 生成文件的策略配置
 * @return
 */
private static StrategyConfig configStratgy() {

    /**
     * 初始化配置
     *      策略中实体字段的默认填充装置
     *      
     */
    List<IFill> tableFillList = makeInitTableFills();


    StrategyConfig strategyConfig = new StrategyConfig.Builder()
            .addInclude(Tables)

            .entityBuilder()//开始定制实体
            /***禁用生成 serialVersionUID**/
            // .disableSerialVersionUID()
            .enableActiveRecord()
            .enableLombok()
            .enableRemoveIsPrefix()
            .enableTableFieldAnnotation()
            .enableChainModel()
            .naming(NamingStrategy.underline_to_camel)
            .columnNaming(NamingStrategy.underline_to_camel)
            /***逻辑删除字段名(数据库)**/
//                .logicDeleteColumnName("yn")
            .addTableFills(tableFillList)
            .idType(IdType.AUTO)
            /**格式化实体类文件名称***/
            //.formatFileName("%sEntity")

            .serviceBuilder()//开始定制Service,由于我们不需要service此处略
            /***格式化 service 接口文件名称**/
            .formatServiceFileName("%sService")
            .formatServiceImplFileName("%sServiceImpl")

            .mapperBuilder()//开始定制映射器
            .enableMapperAnnotation()
            .superClass(BaseMapper.class)
            .enableBaseColumnList()
            .enableBaseResultMap()
            .formatMapperFileName("%sMapper")
            .formatXmlFileName("%sMapper")

            .build();
    return strategyConfig;
}

/**
 * 类生成策略
 *      配置字段默认填充装置
 *
 * @return
 */
private static List<IFill> makeInitTableFills(){
    List<IFill> tableFillList = new ArrayList<>();
    /**定义创建时间 插入时默认填充**/
    Column createTableFill = new Column("created", FieldFill.INSERT);
    /** 定义修改时间 插入或修改时默认填充**/
    Column updateTableFill = new Column("modified", FieldFill.INSERT_UPDATE);
    tableFillList.add(createTableFill);
    tableFillList.add(updateTableFill);

    return tableFillList;
}

/**
 * 设置其他模板
 * @return
 */
private static TemplateConfig configTemplate() {
    TemplateConfig templateConfig = new TemplateConfig.Builder()
            .controller(null)//我不需要controller 此处传null 
            .service(null)//我不需要service  此处传null
            .serviceImpl(null)//我不需要service impl 此处传null
            .build();
    return templateConfig;
}

/**
 *
 * @return
 */
private static InjectionConfig initInjectionConfig(){
    /**自定义生成模板参数**/
    Map<String,Object> paramMap = new HashMap<>();

    /** 自定义 生成类**/
    Map<String,String> customFileMap = new HashMap<>();
    /**PO实体**/
    customFileMap.put("po"+File.separator+"%sPO.java", "/templates/PO.java.vm");
    /**Vo实体**/
    customFileMap.put("vo"+File.separator+"%sVO.java", "/templates/VO.java.vm");
    /**DTO实体**/
    customFileMap.put("dto"+File.separator+"%sDTO.java", "/templates/DTO.java.vm");

    return new InjectionConfig.Builder()
            .customMap(paramMap)
            .customFile(customFileMap)
            .build();
}

以上为配置大多数为mybatis plus generator 3.5.1 的基础配置,网上相关说明资料较多,这里不做过多赘述,以下文章写的较全,大家可以借鉴下。

详见:mybatis-plus代码生成器及配置 - BlogMemory - 博客园

五、着重说明-自定义、定制工具类

1、主要配置方法在以上代码中已列出,为 initInjectionConfig() 方法,需同步配置信息

//1、指定生成的自定文件存放路径
/**存放生成文件的 其他实体类 存放的package地址**/
new PackageConfig.Builder().other(FILE_STORAGE_OTHER_FILE_JAR_PACKAGE);

//2、自定义重新生成自定义、定制类的工具
/**
 * 自定义模板解析器
 */
TimerVelocityTemplateEngine timerVelocityTemplateEngine = new TimerVelocityTemplateEngine();

//3、定义注入配置方法
/**
 * 自定义注入配置
 * @return
 */
private static InjectionConfig initInjectionConfig(){
    /**自定义生成模板参数**/
    Map<String,Object> paramMap = new HashMap<>();

    /** 自定义 生成类**/
    Map<String,String> customFileMap = new HashMap<>();
    /**PO实体**/
    customFileMap.put("po"+File.separator+"%sPO.java", "/templates/PO.java.vm");
    /**Vo实体**/
    customFileMap.put("vo"+File.separator+"%sVO.java", "/templates/VO.java.vm");
    /**DTO实体**/
    customFileMap.put("dto"+File.separator+"%sDTO.java", "/templates/DTO.java.vm");

    return new InjectionConfig.Builder()
            .customMap(paramMap)
            .customFile(customFileMap)
            .build();
}

//4、将自定义注入配置放入到 自动工具生成器中
/**
 * 自定义实体信息
 **/
generator.injection(initInjectionConfig());
//开始执行基础类生成
generator.execute(timerVelocityTemplateEngine);

2、重点说一下 InjectionConfig 注入配置的属性

方法说明作用
beforeOutputFile(BiConsumer<TableInfo, Map<String, Object>>)输出文件之前消费者
customMap(Map<String, Object>)

自定义配置 Map 对象

key:传入参数的名称

value : 传入参数的对象

向自定义模板中传入参数和值
customFile(Map<String, String>)

自定义配置模板文件Map

key:用于定义生成自定义、定制类的名称

value:用于指定自定义、定制类的模板地址,默认为Velocity模板

自定义模板名称和模板

3、详细说明一下 重写的 YaoVelocityTemplateEngine 类

重写后代码:

import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import com.jd.jsf.gd.util.JsonUtils;

public class TimerVelocityTemplateEngine  extends VelocityTemplateEngine {

    @Override
    protected void outputCustomFile( Map<String, String> customFile, TableInfo tableInfo,Map<String, Object> objectMap) {
        //数据库表映射实体名称 
        String entityName = tableInfo.getEntityName();
        
        String otherPath = this.getPathInfo(OutputFile.other);
        //System.out.println(JsonUtils.toJSONString(tableInfo));
        
        //数据库表映射实体名称 驼峰命名法
        objectMap.put("humpEentityName",toLowerCaseFirstOne(entityName));
        
        customFile.forEach((key, value) -> {

            String fileName = String.format(otherPath + File.separator +key,entityName);
            this.outputFile(new File(fileName), objectMap, value);
        });
    }

    /**
     * 首字母转为小写
     * @param s
     * @return
     */
    private  String toLowerCaseFirstOne(String s){
        if(Character.isLowerCase(s.charAt(0))) {
            return s;
        }else {
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }
}

重写前源码:

//AbstractTemplateEngine
protected void outputCustomFile(@NotNull Map<String, String> customFile, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
    String entityName = tableInfo.getEntityName();
    String otherPath = this.getPathInfo(OutputFile.other);
    customFile.forEach((key, value) -> {
        String fileName = String.format(otherPath + File.separator + entityName + File.separator + "%s", key);
        this.outputFile(new File(fileName), objectMap, value);
    });
}

重写原因:

1)在 Velocity 模板中未找到相关的属性,能获取到数据库表映射实体名称的驼峰命名法,重写此方法获得驼峰实体类命名,便于使用

2、生成多个自定义、定制类时没办法随意指定文件路径,一但存在多个类似名称时,非常不便于查找

3、使用源码方式实在是没有想到如何在自定义、定制生成的类名上加上数据库表映射实体名称

通过以上的种种操作就可以实现自定义、定制的实体信息了

六、Velocity 模板案例 

package ${package.Other}.po;

import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.Date;

/**
 * <p>
 * $!{table.comment} 数据表 ${humpEentityName} 数据库表映射实体驼峰名称
 *      基础设施层请求实体
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */
@Getter
@Setter
public class ${entity}PO implements Serializable {

    private static final long serialVersionUID = 1L;

    #foreach($field in ${table.fields})

    #if(${field.keyFlag})
        #set($keyPropertyName=${field.propertyName})
    #end
    #if("$!field.comment" != "")
    /**
     * ${field.comment}
     */
    #end
    private ${field.propertyType} ${field.propertyName};
    #end

    /**
     * 当前页
     */
    private Integer page = 1;

    /**
     * 每页条数
     */
    private Integer pageSize = 20;

}

以上 Velocity 中的相关配置,这里不做相关解释,大家可以直接查看 mybatis plus generator 3.5.1 jar 包中的基础模板中找寻其他配置,你也可以通过 InjectionConfig # beforeOutputFile 方法将入参都打印出来找相应的入参就可以,也可以通过 InjectionConfig # customMap 方法自定义入参。

从上图可看到 mybatis plus generator 3.5.1 在jar 中支持多种生成模板,Velocity只是其中的一种,大家可根据自己的喜好选择相应的模板。

七、总结

mybatis plus generator 的源码相对简单,大家可以通过源码就定制研发。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mybatis plus generator 3.5.1 从了解到自定义定制VO、PO、DTO 的相关文章

随机推荐