mybatis plus generador 3.5.1 Aprenda a personalizar VO, PO, DTO

1. Antecedentes:

Durante el proceso de desarrollo del proyecto, generar un mapeo relacional de objetos ORM a través de herramientas automatizadas es una tarea esencial.

mybatis plus generador es una herramienta muy útil. En un proyecto recién construido, los hermanos de I+D probaron algo nuevo. Utilizaron las versiones 3.5.1 y 3.5.2 del generador. Sobre la base de generar las clases de herramientas básicas que vienen con él Quería generarlos al mismo tiempo. Para las entidades correspondientes como PO, VO, DTO y herramientas de conversión, encontré que hay menos información sobre personalización en 3.5.1 y superior, así que escribí este artículo para registrar el Resultados de la investigacion. Espero que sea bueno para EE.UU.

2. Introducción del paquete jar generador mybatis plus

<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>

3. Breve introducción al entorno de desarrollo.

mac, jdk 1.8, idea, mysql, use la plantilla Velocity para personalizar la clase de herramienta de generación (predeterminada)

4. Instrucciones de configuración básica

1. Configuración de información de ruta básica


/**数据库链接地址**/
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";

El objetivo principal de la configuración anterior es especificar la base de datos, la tabla y la ruta de almacenamiento de archivos básicos generados. No es necesario prestar mucha atención aquí y mirar hacia abajo.

2. Generar automáticamente el método principal de la herramienta.

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);

}

Referencias de paquetes jar relacionados

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. Submétodos clave

/**
 * 配置基础转换器
 * @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();
}

La configuración anterior es principalmente la configuración básica de mybatis plus generador 3.5.1. Hay muchas instrucciones relacionadas en Internet, por lo que no entraré en demasiados detalles aquí. El siguiente artículo es más completo y puede aprender de él.

Para más detalles, consulte: configuración y generador de código mybatis-plus - BlogMemory - Blog Park

5. Énfasis en la explicación: personalización y herramientas de personalización.

1. El método de configuración principal se enumera en el código anterior, que es el método initInjectionConfig (), y la información de configuración debe sincronizarse.

//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. Centrémonos en las propiedades de la configuración de inyección injectionConfig.

método ilustrar efecto
beforeOutputFile(BiConsumer<TableInfo, Map<String, Object>>) archivo de salida antes del consumidor
mapa personalizado(Mapa<Cadena, Objeto>)

Objeto de mapa de configuración personalizada

clave: el nombre del parámetro pasado

valor: el objeto pasado como parámetro

Pasar parámetros y valores a la plantilla personalizada
archivo personalizado(Mapa<Cadena, Cadena>)

Mapa de archivo de plantilla de configuración personalizada

clave: se utiliza para definir el nombre de las clases personalizadas y personalizadas generadas

valor: se utiliza para especificar la dirección de plantilla de clases personalizadas y personalizadas, el valor predeterminado es la plantilla Velocity

Nombre de plantilla personalizado y plantilla

3. Explique en detalle la clase YaoVelocityTemplateEngine reescrita.

Código después de reescribir:

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();
        }
    }
}

Código fuente antes de reescribir:

//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);
    });
}

Motivo de la reescritura:

1) No se encontraron atributos relevantes en la plantilla de Velocity. Se puede obtener el método de denominación de caso de camello del nombre de entidad de mapeo de la tabla de base de datos. Reescriba este método para obtener el nombre de clase de entidad de caso de camello para facilitar su uso.

2. Al generar varias clases personalizadas y personalizadas, no puede especificar la ruta del archivo a voluntad. Una vez que hay varios nombres similares, es muy difícil encontrarlos.

3. Cuando utilicé el método del código fuente, realmente no pensé en cómo agregar el nombre de la entidad de mapeo de la tabla de la base de datos al nombre de clase personalizado o generado de forma personalizada.

A través de las operaciones anteriores, puede lograr información de entidad personalizada y personalizada.

6. Caso de plantilla de velocidad 

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;

}

Las configuraciones relacionadas anteriores en Velocity no se explicarán aquí. Puede consultar directamente la plantilla básica en el paquete jar mybatis plus generador 3.5.1 para encontrar otras configuraciones. También puede usar el método injectionConfig # beforeOutputFile para imprimir todos los parámetros de entrada. para encontrar los correspondientes. Puede usar los parámetros de entrada o puede personalizar los parámetros de entrada a través del método InyecciónConfig #customMap.

Como puede ver en la imagen de arriba, mybatis plus generador 3.5.1 admite múltiples plantillas de generación en el jar. Velocity es solo una de ellas. Puede elegir la plantilla correspondiente según sus propias preferencias.

7. Resumen

El código fuente del generador mybatis plus es relativamente simple y puede personalizarlo y desarrollarlo a través del código fuente.

Supongo que te gusta

Origin blog.csdn.net/TimerBin/article/details/127799360
Recomendado
Clasificación