MyBatis-Plus Generator 数据库实体类模板化实现:添加表字段常量,避免逻辑层的字段硬编码

UpdateWrapper<CetdSystemParam> update=new UpdateWrapper<>();
update.eq("Param_Type", 0);
update.set("Param_Value", millSecond);
try {
    cetdSystemParamMapper.update(null, update);
} catch (Exception e) {
    log.error(ServerConstants.LOGGER_PREFIX + "[设置banner图片切换的时间,单位:毫秒异常!millSecond:" + millSecond);
}

 

update.eq("Param_Type", 0); update.set("Param_Value", millSecond);这两行代码,硬编码简直让人难受!一旦数据库改了字段,必须把逻辑层全部肉眼检查一遍,简直是灾难!

为了解决这个,我第一个想到的是:手动写常量,给每一个实体类加上全部的数据库字段名常量,例如:


    public static final String PARAM_ID="Param_ID";
    public static final String PARAM_NAME="Param_Name";

但是,仍然要手改。于是,我选择从模板入手:既然那些java实体类都是按模板来的,我应该可以通过修改模板来实现我想要的效果----给每个实体类添加对应表的全部原始字段名,作为该类的公开静态常量。

核心解决方案,改了模板,加入了这几段代码(beetl语言),使实体类里加入数据库字段常量:

<% /** -----------BEGIN 字段循环遍历,写入数据库原始字段作为常量 by:Chuck----------- **/ %>

/***** * 数据库原始字段 *******/

<% for(field in table.fields){ %>

<%

var a = field.name;

var result = strutil.toUpperCase (a);

%>

public static final String ${result}="${field.name}";

<% }

%>

<% /** -----------END 字段循环遍历,写入数据库原始字段作为常量 by:Chuck----------- **/ %>

==================================================================================================

 

pom.xml:

<!-- 代码生成器依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
</dependency>

<dependency>
    <groupId>com.ibeetl</groupId>
    <artifactId>beetl</artifactId>
</dependency>

 

EntityGenerator.java

核心代码:

// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 使用自定义模板,不想要生成就设置为null,如果不设置null会使用默认模板
templateConfig.setEntity("templates/lombok_swagger2_entity.java");
templateConfig.setService(null);
templateConfig.setServiceImpl(null);
templateConfig.setController(null);
templateConfig.setMapper(null);
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);

=============================================================

 

package com.linklink.cetd.admin;


import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.ITypeConvert;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
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.engine.BeetlTemplateEngine;

import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashMap;
import java.util.Map;

/*
    数据层内容生成
 */
@SpringBootTest
public class EntityGenerator {

    // 生成输出目录,定位到工程的java目录下
    //D:\chuck\ideaProjects\cetd\cetd_applications\AdminApplication\AdminMain\src\main\java
    private static String outputDir = "D:\\chuck\\ideaProjects\\cetd\\cetd_applications\\AdminApplication\\AdminMain\\src\\main\\java";
    // 生成类的作者
    private static String author = "chuck";
    // 数据源相关配置
    private static String url = "jdbc:mysql://xxxx:20000/yanguan_cetd?autoReconnect=true&characterEncoding=UTF-8&serverTimezone=UTC";
    private static String driverName = "com.mysql.cj.jdbc.Driver";
    private static String userName = "xxxx";
    private static String userPwd = "xxxx";
    // DAO的包路径
    private static String daoPackage = "com.linklink.cetd.admin.dao";
    // 待生成的表名,注意是覆盖更新
    private static String[] tableNames;

    static {
        tableNames = new String[]{
                "cetd_banner",
                "cetd_account",
                "cetd_system_param",
                "cetd_item",
                "cetd_item_model",
                "cetd_item_category",
                "cetd_hot_item",
                "cetd_message",
                "cetd_usr_msg"

        };
    }


    @Test
    public void entityGenerator() {






        AutoGenerator mpg = new AutoGenerator();
        mpg.setTemplateEngine(new BeetlTemplateEngine());


        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        // 使用自定义模板,不想要生成就设置为null,如果不设置null会使用默认模板
        templateConfig.setEntity("templates/lombok_swagger2_entity.java");
        templateConfig.setService(null);
        templateConfig.setServiceImpl(null);
        templateConfig.setController(null);
        templateConfig.setMapper(null);
        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);







        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        gc.setOutputDir(outputDir);
        gc.setFileOverride(true);
        gc.setSwagger2(true);//注意这里,我用了swagger2
        gc.setActiveRecord(true);
        gc.setEnableCache(false);
        gc.setBaseResultMap(true);
        gc.setBaseColumnList(false);
        gc.setAuthor(author);
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(url);
        // dsc.setSchemaName("public");
        dsc.setDriverName(driverName);
        dsc.setUsername(userName);
        dsc.setPassword(userPwd);
        //避免把tinyint变为boolean
        dsc.setTypeConvert(new MySqlTypeConvertCustom());
        mpg.setDataSource(dsc);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        //strategy.setTablePrefix(new String[]{"_"});// 此处可以修改为您的表前缀
        strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
        strategy.setInclude(tableNames);
        strategy.setEntityLombokModel(true);//开启了lombok
        mpg.setStrategy(strategy);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent(null);
        pc.setEntity(daoPackage + ".entity");
        pc.setMapper(daoPackage + ".mapper");
        pc.setXml(daoPackage + ".mapper.xml");
        mpg.setPackageInfo(pc);

        // 注入自定义配置,可以在 VM 中使用 cfg.abc 设置的值
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<>();
                map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
                this.setMap(map);
            }
        };

        mpg.setCfg(cfg);

        // 执行生成
        mpg.execute();

        // 打印注入设置
        System.err.println(mpg.getCfg().getMap().get("abc"));

    }

    /**
     * 自定义类型转换
     */
    class MySqlTypeConvertCustom extends MySqlTypeConvert implements ITypeConvert {
        @Override
        public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
            String t = fieldType.toLowerCase();
            if (t.contains("tinyint")) {
                return DbColumnType.INTEGER;
            }
            if (t.contains("int")) {
                return DbColumnType.INTEGER;
            }
            if (t.contains("datetime")) {
                return DbColumnType.DATE;
            }
            if (t.contains("timestamp")) {
                return DbColumnType.DATE;
            }
            return super.processTypeConvert(globalConfig, fieldType);
        }
    }

}
 entity.java.btl(普通模板)
package ${package.Entity};
<% for(pkg in table.importPackages){ %>
import ${pkg};
<% } %>
<% if(swagger2){ %>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
<% } %>
<% if(entityLombokModel){ %>
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
<% } %>
/**
 * <p>
 * ${table.comment!}
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */
<% if(entityLombokModel){ %>
@Data
    <% if(isNotEmpty(superEntityClass)){ %>
@EqualsAndHashCode(callSuper = true)
    <% }else{ %>
@EqualsAndHashCode(callSuper = false)
    <% } %>
@Accessors(chain = true)
<% } %>
<% if(table.convert){ %>
@TableName("${table.name}")
<% } %>
<% if(swagger2){ %>
@ApiModel(value="${entity}对象", description="${table.comment!''}")
<% } %>
<% if(isNotEmpty(superEntityClass)){ %>
public class ${entity} extends ${superEntityClass}<% if(activeRecord){ %><${entity}><%}%>{
<% }else if(activeRecord){ %>
public class ${entity} extends Model<${entity}> {
<% }else{ %>
public class ${entity} implements Serializable {
<% } %>

<% if(entitySerialVersionUID){ %>
    private static final long serialVersionUID = 1L;
<% } %>
<% /** -----------BEGIN 字段循环遍历,写入数据库原始字段作为常量 by:Chuck----------- **/ %>


    /*****
        * 数据库原始字段
    *******/
<% for(field in table.fields){ %>
<%
var a = field.name;
var result = strutil.toUpperCase (a);
%>
    public static final String ${result}="${field.name}";
<% } %>
<% /** -----------END 字段循环遍历,写入数据库原始字段作为常量 by:Chuck----------- **/ %>

<% /** -----------BEGIN 字段循环遍历----------- **/ %>
<% for(field in table.fields){ %>
    <%
    if(field.keyFlag){
        var keyPropertyName = field.propertyName;
    }
    %>

    <% if(isNotEmpty(field.comment)){ %>
        <% if(swagger2){ %>
    @ApiModelProperty( value = "${field.comment}" , required = true)
        <% }else{ %>
    /**
     * ${field.comment}
     */
        <% } %>
    <% } %>
    <% if(field.keyFlag){ %>
    <%
    /*主键*/
    %>
        <% if(field.keyIdentityFlag){ %>
    @TableId(value = "${field.name}", type = IdType.AUTO)
        <% }else if(isNotEmpty(idType)){ %>
    @TableId(value = "${field.name}", type = IdType.${idType})
        <% }else if(field.convert){ %>
    @TableId("${field.name}")
         <% } %>
    <%
    /*普通字段*/
    %>
    <% }else if(isNotEmpty(field.fill)){ %>
        <% if(field.convert){ %>
    @TableField(value = "${field.name}", fill = FieldFill.${field.fill})
        <% }else{ %>
    @TableField(fill = FieldFill.${field.fill})
        <% } %>
    <% }else if(field.convert){ %>
    @TableField("${field.name}")
    <% } %>
    <%
    /*乐观锁注解*/
    %>
    <% if(versionFieldName!'' == field.name){ %>
    @Version
    <% } %>
    <%
    /*逻辑删除注解*/
    %>
    <% if(logicDeleteFieldName!'' == field.name){ %>
    @TableLogic
    <% } %>
    private ${field.propertyType} ${field.propertyName};
<% } %>
<% /** -----------END 字段循环遍历----------- **/ %>

<% if(!entityLombokModel){ %>
    <% for(field in table.fields){ %>
        <%
        var getprefix ='';
        if(field.propertyType=='boolean'){
            getprefix='is';
        }else{
            getprefix='get';
        }
        %>
    public ${field.propertyType} ${getprefix}${field.capitalName}() {
        return ${field.propertyName};
    }

        <% if(entityBuilderModel){ %>
    public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
        <% }else{ %>
    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
        <% } %>
        this.${field.propertyName} = ${field.propertyName};
        <% if(entityBuilderModel){ %>
        return this;
        <% } %>
    }

    <% } %>
<% } %>
<% if(entityColumnConstant){ %>
   <% for(field in table.fields){ %>
    public static final String ${strutil.toUpperCase(field.name)} = "${field.name}";

   <% } %>
<% } %>
<% if(activeRecord){ %>
    @Override
    protected Serializable pkVal() {
    <% if(isNotEmpty(keyPropertyName)){ %>
        return this.${keyPropertyName};
    <% }else{ %>
        return null;
    <% } %>
    }

<% } %>
<% if(!entityLombokModel){ %>
    @Override
    public String toString() {
        return "${entity}{" +
    <% for(field in table.fields){ %>
       <% if(fieldLP.index==0){ %>
        "${field.propertyName}=" + ${field.propertyName} +
       <% }else{ %>
        ", ${field.propertyName}=" + ${field.propertyName} +
       <% } %>
    <% } %>
        "}";
    }
<% } %>
}

=====================================================

lombok_swagger2_entity.java.btl(使用了lombok和swagger2的模板)

package ${package.Entity};
<% for(pkg in table.importPackages){ %>
import ${pkg};
<% } %>
<% if(swagger2){ %>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
<% } %>
<% if(entityLombokModel){ %>
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
<% } %>
/**
 * <p>
 * ${table.comment!}
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */
<% if(entityLombokModel){ %>
@Data
<% } %>
<% if(table.convert){ %>
@TableName("${table.name}")
<% } %>
<% if(swagger2){ %>
@ApiModel(value="${entity}对象", description="${table.comment!''}")
<% } %>
<% if(isNotEmpty(superEntityClass)){ %>
public class ${entity} extends ${superEntityClass}<% if(activeRecord){ %><${entity}><%}%>{
<% }else if(activeRecord){ %>
public class ${entity} extends Model<${entity}> {
<% }else{ %>
public class ${entity} implements Serializable {
<% } %>

<% if(entitySerialVersionUID){ %>
    private static final long serialVersionUID = 1L;
<% } %>
<% /** -----------BEGIN 字段循环遍历,写入数据库原始字段作为常量 by:Chuck----------- **/ %>


    /*****
        * 数据库原始字段
    *******/
<% for(field in table.fields){ %>
<%
var a = field.name;
var result = strutil.toUpperCase (a);
%>
    public static final String ${result}="${field.name}";
<% } %>
<% /** -----------END 字段循环遍历,写入数据库原始字段作为常量 by:Chuck----------- **/ %>

<% /** -----------BEGIN 字段循环遍历----------- **/ %>
<% for(field in table.fields){ %>
    <%
    if(field.keyFlag){
        var keyPropertyName = field.propertyName;
    }
    %>

    <% if(isNotEmpty(field.comment)){ %>
        <% if(swagger2){ %>
    @ApiModelProperty( value = "${field.comment}" , required = true)
        <% }else{ %>
    /**
     * ${field.comment}
     */
        <% } %>
    <% } %>
    <% if(field.keyFlag){ %>
    <%
    /*主键*/
    %>
        <% if(field.keyIdentityFlag) { %>
    @TableId(value = "${field.name}", type = IdType.AUTO)
        <% }else if(isNotEmpty(idType)){ %>
    @TableId(value = "${field.name}", type = IdType.${idType})
        <% }else if(field.convert){ %>
    @TableId("${field.name}")
         <% } %>
    <%
    /*普通字段*/
    %>
    <% } %>
    <%
    /*乐观锁注解*/
    %>
    <% if(versionFieldName!'' == field.name){ %>
    @Version
    <% } %>
    <%
    /*逻辑删除注解*/
    %>
    <% if(logicDeleteFieldName!'' == field.name){ %>
    @TableLogic
    <% } %>
    private ${field.propertyType} ${field.propertyName};
<% } %>
<% /** -----------END 字段循环遍历----------- **/ %>

<% if(!entityLombokModel){ %>
    <% for(field in table.fields){ %>
        <%
        var getprefix ='';
        if(field.propertyType=='boolean'){
            getprefix='is';
        }else{
            getprefix='get';
        }
        %>
    public ${field.propertyType} ${getprefix}${field.capitalName}() {
        return ${field.propertyName};
    }

        <% if(entityBuilderModel){ %>
    public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
        <% }else{ %>
    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
        <% } %>
        this.${field.propertyName} = ${field.propertyName};
        <% if(entityBuilderModel){ %>
        return this;
        <% } %>
    }

    <% } %>
<% } %>
<% if(entityColumnConstant){ %>
   <% for(field in table.fields){ %>
    public static final String ${strutil.toUpperCase(field.name)} = "${field.name}";

   <% } %>
<% } %>
<% if(activeRecord){ %>
    @Override
    protected Serializable pkVal() {
    <% if(isNotEmpty(keyPropertyName)){ %>
        return this.${keyPropertyName};
    <% }else{ %>
        return null;
    <% } %>
    }

<% } %>
<% if(!entityLombokModel){ %>
    @Override
    public String toString() {
        return "${entity}{" +
    <% for(field in table.fields){ %>
       <% if(fieldLP.index==0){ %>
        "${field.propertyName}=" + ${field.propertyName} +
       <% }else{ %>
        ", ${field.propertyName}=" + ${field.propertyName} +
       <% } %>
    <% } %>
        "}";
    }
<% } %>
}

 

生成的实体类(我用的是带lombok和swagger的模板,不需要则用另外一套模板):

package com.linklink.cetd.admin.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
 * <p>
 * 系统参数
 * </p>
 *
 * @author chuck
 * @since 2020-04-04
 */
@Data
@ApiModel(value="CetdSystemParam对象", description="系统参数")
public class CetdSystemParam extends Model<CetdSystemParam> {

    private static final long serialVersionUID = 1L;


    /*****
        * 数据库原始字段
    *******/
    public static final String PARAM_ID="Param_ID";
    public static final String PARAM_NAME="Param_Name";
    public static final String PARAM_VALUE="Param_Value";
    public static final String PARAM_TYPE="Param_Type";
    public static final String PARAM_DESC="Param_Desc";
    public static final String CTIME="CTime";


    @ApiModelProperty( value = "参数ID" , required = true)
    @TableId(value = "Param_ID", type = IdType.AUTO)
    private Integer paramId;

    @ApiModelProperty( value = "参数名" , required = true)
    private String paramName;

    @ApiModelProperty( value = "参数值" , required = true)
    private String paramValue;

    @ApiModelProperty( value = "参数类型 0-banenr切换时间(毫秒) " , required = true)
    private Integer paramType;

    private String paramDesc;

    @ApiModelProperty( value = "创建时间" , required = true)
    private Date CTime;

    @Override
    protected Serializable pkVal() {
        return null;
    }

}

 

 

告别字段硬编码。因为每个实体类对应数据库的字段名都是常量了,自动生成的:

UpdateWrapper<CetdSystemParam> update=new UpdateWrapper<>();
update.eq(CetdSystemParam.PARAM_TYPE, 0);
update.set(CetdSystemParam.PARAM_VALUE , millSecond);
try {
    cetdSystemParamMapper.update(null, update);
} catch (Exception e) {
    log.error(ServerConstants.LOGGER_PREFIX + "[设置banner图片切换的时间,单位:毫秒异常!millSecond:" + millSecond);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值