Mybatis-Plus代码生成器详解及完整代码实现

意义

1、日常开发过程中,常规后端开发接收到需求后,进行数据库E-R设计后创建对应数据表。无论基于speingmvc还是strtus(同样是一个mvc框架),都需要进行一些固定模板的创建,如:entity、controller、service、impl、mapper等,重复ctrl c + v。
2、公司开发经常会由多个小组或多人进行,统一的代码格式将有利于工作推进(尤其在新手较多的公司)。

前提

本文基于mybatis-plus 3.5.2及以上版本,模板引擎使用freemarker。生成的模板代码符合常规前后端开发模式(springboot + mybatis-plus),符合rest风格,建议创建数据表时写注释,生成的entity代码可读性更强。代码可直接使用,模板可按实际规范调整。

项目结构

Mybatis-Plus代码生成器详解及完整代码实现_第1张图片
resource – 配置文件、模板文件
pom.xml – jar包依赖

pom.xml


        
            com.baomidou
            mybatis-plus-generator
            3.5.2
        
        
            com.baomidou
            mybatis-plus
            3.5.2
        
        
            mysql
            mysql-connector-java
        
        
           org.springframework.boot
           spring-boot-starter-freemarker
       
    

generatorConf.propertites

建议使用配置文件的方式便于调整,相关配置也可在代码中写死

## dataSource数据库配置
# mysql 数据库类型
dbType=mysql
url=jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username=root
password=1234567890
## globalConfig全局配置
projectPath=E://gen
module=/camp
author=HS

核心代码

1、配置类

package com.camp.gen.config;

import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.querys.DMQuery;
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.function.ConverterFileName;
import com.baomidou.mybatisplus.generator.keywords.MySqlKeyWordsHandler;
import com.camp.gen.handler.DmKeyWordsHandler;
import org.apache.ibatis.cache.Cache;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * @Description 代码生成器核心配置
 * @Author HS
 * @Date 2022/12/5 10:31
 */
public class GeneratorConfig {
    /**
     * 配置文件
     */
    private static ResourceBundle generatorConf;

    static {
        generatorConf = ResourceBundle.getBundle("generatorConf");
    }

    public static DataSourceConfig initDataSourceConfig() {
        String dbType = generatorConf.getString("dbType");
        IDbQuery query;
        IKeyWordsHandler keyWordsHandler;
        switch (dbType){
            case "dm":
                query = new DMQuery();
                keyWordsHandler = new DmKeyWordsHandler();
                break;
            default:
                query = new MySqlQuery();
                keyWordsHandler = new MySqlKeyWordsHandler();
                break;
        }
        DataSourceConfig dataSourceConfig = new DataSourceConfig
                .Builder(generatorConf.getString("url"), generatorConf.getString("username"), generatorConf.getString("password"))
                .dbQuery(query)
                //自定义数据库-java类型转换器,具体类需继承MySqlTypeConvert
                //.typeConvert(new MySqlTypeConvert())
                .keyWordsHandler(keyWordsHandler)
                .build();
        return  dataSourceConfig;
    }

    /**
     * 全局配置
     * @return
     */
    public static GlobalConfig initGlobalConfig(){
        // 全局配置
        GlobalConfig gc = new GlobalConfig.Builder()
                //设置输出文件路径
                .outputDir(generatorConf.getString("projectPath") +generatorConf.getString("module"))
                .author(generatorConf.getString("author"))
                //执行完 是否打开输出的目录,默认true
                .disableOpenDir()
                // 设置日期类型为Date(若不设置时间类型都会变成LocalDateTime部分连接池例如druid是无法识别的)
                .dateType(DateType.ONLY_DATE)
                .build();
        return gc;
    }

    /**
     * 包配置
     * @return
     */
    public static PackageConfig initPackageConfig(){
        // 包配置
        PackageConfig pc = new PackageConfig.Builder()
                //父包
                .parent("com.css.cssbase.modules")
                //自定义实体包名
                .entity("entity")
                //自定义mapper包名
                .mapper("mapper")
                //自定义mapper.xml包名
                .xml("mapper.xmls")
                //自定义service包名
                .service("service")
                //自定义serviceImpl包名
                .serviceImpl("service.impl")
                //自定义controller包名
                .controller("controller")
                //自定义包名
                .other("domain")
                .build();
        return pc;
    }

    /**
     * 模板配置
     * @return
     */
    public static TemplateConfig initTemplateConfig(){
        // 配置模板
        TemplateConfig tc = new TemplateConfig.Builder()
                .entity("vm/java/entity.java")
                .controller("vm/java/controller.java")
                .mapper("vm/java/mapper.java")
                .service("vm/java/service.java")
                .serviceImpl("vm/java/serviceImpl.java")
                .xml("vm/xml/mapper.xml")
                .build();
        return tc;
    }

    /**
     * 策略配置
     * @return
     */
    public static StrategyConfig initStrategyConfig(List tableNames){
        // 策略配置
        StrategyConfig strategy = new StrategyConfig.Builder()
                .addInclude(tableNames)
                //定制实体
                .entityBuilder()
                .enableLombok()
                .naming(NamingStrategy.underline_to_camel)
                .columnNaming(NamingStrategy.underline_to_camel)
                //生成实体时生成数据库字段注解
                .enableTableFieldAnnotation()
                //定制controller
                .controllerBuilder()
                //是否rest模式
                .enableRestStyle()
                //定制service & Impl
                .serviceBuilder()
                //service命名规则
                .convertServiceFileName(new ConverterFileName() {
                    @NotNull
                    @Override
                    public String convert(String entityName) {
                        return entityName + ConstVal.SERVICE;
                    }
                })
                //定制mapper
                .mapperBuilder()
                .enableBaseColumnList()
                .enableBaseResultMap()
                //TODO 需根据实际缓存调整
                .cache(Cache.class)
                .build();
        return strategy;
    }

    /**
     * 注入自定义配置-参数、生成类
     * @return
     */
    public static InjectionConfig initInjectionConfig(Map parameterMap){
        //自定义生成类
        HashMap customFileMap = new HashMap<>(4);
        //Vo实体
        customFileMap.put(File.separator+"%sVO.java", "vm/java/vo.java.ftl");
        //DTO实体
        customFileMap.put(File.separator+"%sDTO.java", "vm/java/dto.java.ftl");

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

2、自定义模板解析器,不需要可不写(此处用于生成domain下的dto、vo)

package com.camp.gen.handler;

import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.Map;

/**
 * @Description 自定义模板解析器
 * @Author HS
 * @Date 2022/11/28 15:24
 */
public class MyFreeMarkerTemplateEngine extends FreemarkerTemplateEngine {
    @Override
    protected void outputCustomFile(@NotNull Map customFile, @NotNull TableInfo tableInfo, @NotNull Map objectMap) {
        //数据库表映射实体名称
        String entityName = tableInfo.getEntityName();

        String otherPath = this.getPathInfo(OutputFile.other);
        //System.out.println(JsonUtils.toJSONString(tableInfo));

        customFile.forEach((key, value) -> {
            String fileName = String.format(otherPath + File.separator +key,entityName);
            this.outputFile(new File(fileName), objectMap, value, false);
        });
    }
}

3、数据库关键字处理类,使用的数据库有相关实现的可不写(官方提供mysql、oracle等常用数据库关键字处理类,此处用户扩展国产数据库)

package com.camp.gen.handler;

import com.baomidou.mybatisplus.generator.keywords.BaseKeyWordsHandler;
import org.jetbrains.annotations.NotNull;

import java.util.*;

/**
 * @Description dm关键字处理类
 * @Author HS
 * @Date 2022/12/5 11:07
 */
public class DmKeyWordsHandler extends BaseKeyWordsHandler {

    private static final List KEY_WORDS = new ArrayList(Arrays.asList("ACCESSIBLE", "ACCOUNT", "ACTION", "ACTIVE", "ADD", "ADMIN", "AFTER", "AGAINST", "AGGREGATE", "ALGORITHM", "ALL", "ALTER", "ALWAYS", "ANALYSE", "ANALYZE", "AND", "ANY", "ARRAY", "AS", "ASC", "ASCII", "ASENSITIVE", "AT", "ATTRIBUTE", "AUTHENTICATION", "AUTOEXTEND_SIZE", "AUTO_INCREMENT", "AVG", "AVG_ROW_LENGTH", "BACKUP", "BEFORE", "BEGIN", "BETWEEN", "BIGINT", "BINARY", "BINLOG", "BIT", "BLOB", "BLOCK", "BOOL", "BOOLEAN", "BOTH", "BTREE", "BUCKETS", "BY", "BYTE", "CACHE", "CALL", "CASCADE", "CASCADED", "CASE", "CATALOG_NAME", "CHAIN", "CHALLENGE_RESPONSE", "CHANGE", "CHANGED", "CHANNEL", "CHAR", "CHARACTER", "CHARSET", "CHECK", "CHECKSUM", "CIPHER", "CLASS_ORIGIN", "CLIENT", "CLONE", "CLOSE", "COALESCE", "CODE", "COLLATE", "COLLATION", "COLUMN", "COLUMNS", "COLUMN_FORMAT", "COLUMN_NAME", "COMMENT", "COMMIT", "COMMITTED", "COMPACT", "COMPLETION", "COMPONENT", "COMPRESSED", "COMPRESSION", "CONCURRENT", "CONDITION", "CONNECTION", "CONSISTENT", "CONSTRAINT", "CONSTRAINT_CATALOG", "CONSTRAINT_NAME", "CONSTRAINT_SCHEMA", "CONTAINS", "CONTEXT", "CONTINUE", "CONVERT", "CPU", "CREATE", "CROSS", "CUBE", "CUME_DIST", "CURRENT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "CURSOR_NAME", "DATA", "DATABASE", "DATABASES", "DATAFILE", "DATE", "DATETIME", "DAY", "DAY_HOUR", "DAY_MICROSECOND", "DAY_MINUTE", "DAY_SECOND", "DEALLOCATE", "DEC", "DECIMAL", "DECLARE", "DEFAULT", "DEFAULT_AUTH", "DEFINER", "DEFINITION", "DELAYED", "DELAY_KEY_WRITE", "DELETE", "DENSE_RANK", "DESC", "DESCRIBE", "DESCRIPTION", "DES_KEY_FILE", "DETERMINISTIC", "DIAGNOSTICS", "DIRECTORY", "DISABLE", "DISCARD", "DISK", "DISTINCT", "DISTINCTROW", "DIV", "DO", "DOUBLE", "DROP", "DUAL", "DUMPFILE", "DUPLICATE", "DYNAMIC", "EACH", "ELSE", "ELSEIF", "EMPTY", "ENABLE", "ENCLOSED", "ENCRYPTION", "END", "ENDS", "ENFORCED", "ENGINE", "ENGINE_ATTRIBUTE", "ENGINES", "ENUM", "ERROR", "ERRORS", "ESCAPE", "ESCAPED", "EVENT", "EVENTS", "EVERY", "EXCEPT", "EXCHANGE", "EXCLUDE", "EXECUTE", "EXISTS", "EXIT", "EXPANSION", "EXPIRE", "EXPLAIN", "EXPORT", "EXTENDED", "EXTENT_SIZE", "FACTOR", "FAILED_LOGIN_ATTEMPTS", "FALSE", "FAST", "FAULTS", "FETCH", "FIELDS", "FILE", "FILE_BLOCK_SIZE", "FILTER", "FINISH", "FIRST", "FIRST_VALUE", "FIXED", "FLOAT", "FLOAT4", "FLOAT8", "FLUSH", "FOLLOWING", "FOLLOWS", "FOR", "FORCE", "FOREIGN", "FORMAT", "FOUND", "FROM", "FULL", "FULLTEXT", "FUNCTION", "GENERAL", "GENERATED", "GEOMCOLLECTION", "GEOMETRY", "GEOMETRYCOLLECTION", "GET", "GET_FORMAT", "GET_MASTER_PUBLIC_KEY", "GET_SOURCE_PUBLIC_KEY", "GLOBAL", "GRANT", "GRANTS", "GROUP", "GROUP_REPLICATION", "GROUPING", "GROUPS", "GTID_ONLY", "HANDLER", "HASH", "HAVING", "HELP", "HIGH_PRIORITY", "HISTOGRAM", "HISTORY", "HOST", "HOSTS", "HOUR", "HOUR_MICROSECOND", "HOUR_MINUTE", "HOUR_SECOND", "IDENTIFIED", "IF", "IGNORE", "IGNORE_SERVER_IDS", "IMPORT", "IN", "INACTIVE", "INDEX", "INDEXES", "INFILE", "INITIAL", "INITIAL_SIZE", "INITIATE", "INNER", "INOUT", "INSENSITIVE", "INSERT", "INSERT_METHOD", "INSTALL", "INSTANCE", "INT", "INT1", "INT2", "INT3", "INT4", "INT8", "INTEGER", "INTERVAL", "INTO", "INVISIBLE", "INVOKER", "IO", "IO_AFTER_GTIDS", "IO_BEFORE_GTIDS", "IO_THREAD", "IPC", "IS", "ISOLATION", "ISSUER", "ITERATE", "JOIN", "JSON", "JSON_TABLE", "JSON_VALUE", "KEY", "KEYS", "KEY_BLOCK_SIZE", "KEYRING", "KILL", "LAG", "LANGUAGE", "LAST", "LAST_VALUE", "LATERAL", "LEAD", "LEADING", "LEAVE", "LEAVES", "LEFT", "LESS", "LEVEL", "LIKE", "LIMIT", "LINEAR", "LINES", "LINESTRING", "LIST", "LOAD", "LOCAL", "LOCALTIME", "LOCALTIMESTAMP", "LOCK", "LOCKED", "LOCKS", "LOGFILE", "LOGS", "LONG", "LONGBLOB", "LONGTEXT", "LOOP", "LOW_PRIORITY", "MASTER", "MASTER_AUTO_POSITION", "MASTER_BIND", "MASTER_COMPRESSION_ALGORITHMS", "MASTER_CONNECT_RETRY", "MASTER_DELAY", "MASTER_HEARTBEAT_PERIOD", "MASTER_HOST", "MASTER_LOG_FILE", "MASTER_LOG_POS", "MASTER_PASSWORD", "MASTER_PORT", "MASTER_PUBLIC_KEY_PATH", "MASTER_RETRY_COUNT", "MASTER_SERVER_ID", "MASTER_SSL", "MASTER_SSL_CA", "MASTER_SSL_CAPATH", "MASTER_SSL_CERT", "MASTER_SSL_CIPHER", "MASTER_SSL_CRL", "MASTER_SSL_CRLPATH", "MASTER_SSL_KEY", "MASTER_SSL_VERIFY_SERVER_CERT", "MASTER_TLS_CIPHERSUITES", "MASTER_TLS_VERSION", "MASTER_USER", "MASTER_ZSTD_COMPRESSION_LEVEL", "MATCH", "MAXVALUE", "MAX_CONNECTIONS_PER_HOUR", "MAX_QUERIES_PER_HOUR", "MAX_ROWS", "MAX_SIZE", "MAX_STATEMENT_TIME", "MAX_UPDATES_PER_HOUR", "MAX_USER_CONNECTIONS", "MEDIUM", "MEDIUMBLOB", "MEDIUMINT", "MEDIUMTEXT", "MEMBER", "MEMORY", "MERGE", "MESSAGE_TEXT", "MICROSECOND", "MIDDLEINT", "MIGRATE", "MINUTE", "MINUTE_MICROSECOND", "MINUTE_SECOND", "MIN_ROWS", "MOD", "MODE", "MODIFIES", "MODIFY", "MONTH", "MULTILINESTRING", "MULTIPOINT", "MULTIPOLYGON", "MUTEX", "MYSQL_ERRNO", "NAME", "NAMES", "NATIONAL", "NATURAL", "NCHAR", "NDB", "NDBCLUSTER", "NESTED", "NETWORK_NAMESPACE", "NEVER", "NEW", "NEXT", "NO", "NODEGROUP", "NONBLOCKING", "NONE", "NOT", "NOWAIT", "NO_WAIT", "NO_WRITE_TO_BINLOG", "NTH_VALUE", "NTILE", "NULL", "NULLS", "NUMBER", "NUMERIC", "NVARCHAR", "OF", "OFF", "OFFSET", "OJ", "OLD", "OLD_PASSWORD", "ON", "ONE", "ONLY", "OPEN", "OPTIMIZE", "OPTIMIZER_COSTS", "OPTION", "OPTIONAL", "OPTIONALLY", "OPTIONS", "OR", "ORDER", "ORDINALITY", "ORGANIZATION", "OTHERS", "OUT", "OUTER", "OUTFILE", "OVER", "OWNER", "PACK_KEYS", "PAGE", "PARSER", "PARSE_GCOL_EXPR", "PARTIAL", "PARTITION", "PARTITIONING", "PARTITIONS", "PASSWORD", "PASSWORD_LOCK_TIME", "PATH", "PERCENT_RANK", "PERSIST", "PERSIST_ONLY", "PHASE", "PLUGIN", "PLUGINS", "PLUGIN_DIR", "POINT", "POLYGON", "PORT", "PRECEDES", "PRECEDING", "PRECISION", "PREPARE", "PRESERVE", "PREV", "PRIMARY", "PRIVILEGE_CHECKS_USER", "PRIVILEGES", "PROCEDURE", "PROCESS", "PROCESSLIST", "PROFILE", "PROFILES", "PROXY", "PURGE", "QUARTER", "QUERY", "QUICK", "RANDOM", "RANGE", "RANK", "READ", "READS", "READ_ONLY", "READ_WRITE", "REAL", "REBUILD", "RECOVER", "RECURSIVE", "REDOFILE", "REDO_BUFFER_SIZE", "REDUNDANT", "REFERENCE", "REFERENCES", "REGEXP", "REGISTRATION", "RELAY", "RELAYLOG", "RELAY_LOG_FILE", "RELAY_LOG_POS", "RELAY_THREAD", "RELEASE", "RELOAD", "REMOVE", "RENAME", "REORGANIZE", "REPAIR", "REPEAT", "REPEATABLE", "REPLACE", "REPLICA", "REPLICAS", "REPLICATE_DO_DB", "REPLICATE_DO_TABLE", "REPLICATE_IGNORE_DB", "REPLICATE_IGNORE_TABLE", "REPLICATE_REWRITE_DB", "REPLICATE_WILD_DO_TABLE", "REPLICATE_WILD_IGNORE_TABLE", "REPLICATION", "REQUIRE", "REQUIRE_ROW_FORMAT", "RESET", "RESIGNAL", "RESOURCE", "RESPECT", "RESTART", "RESTORE", "RESTRICT", "RESUME", "RETAIN", "RETURN", "RETURNED_SQLSTATE", "RETURNING", "RETURNS", "REUSE", "REVERSE", "REVOKE", "RIGHT", "RLIKE", "ROLE", "ROLLBACK", "ROLLUP", "ROTATE", "ROUTINE", "ROW", "ROWS", "ROW_COUNT", "ROW_FORMAT", "ROW_NUMBER", "RTREE", "SAVEPOINT", "SCHEDULE", "SCHEMA", "SCHEMAS", "SCHEMA_NAME", "SECOND", "SECOND_MICROSECOND", "SECONDARY", "SECONDARY_ENGINE", "SECONDARY_ENGINE_ATTRIBUTE", "SECONDARY_LOAD", "SECONDARY_UNLOAD", "SECURITY", "SELECT", "SENSITIVE", "SEPARATOR", "SERIAL", "SERIALIZABLE", "SERVER", "SESSION", "SET", "SHARE", "SHOW", "SHUTDOWN", "SIGNAL", "SIGNED", "SIMPLE", "SKIP", "SLAVE", "SLOW", "SMALLINT", "SNAPSHOT", "SOCKET", "SOME", "SONAME", "SOUNDS", "SOURCE", "SOURCE_AUTO_POSITION", "SOURCE_BIND", "SOURCE_COMPRESSION_ALGORITHMS", "SOURCE_CONNECT_RETRY", "SOURCE_DELAY", "SOURCE_HEARTBEAT_PERIOD", "SOURCE_HOST", "SOURCE_LOG_FILE", "SOURCE_LOG_POS", "SOURCE_PASSWORD", "SOURCE_PORT", "SOURCE_PUBLIC_KEY_PATH", "SOURCE_RETRY_COUNT", "SOURCE_SSL", "SOURCE_SSL_CA", "SOURCE_SSL_CAPATH", "SOURCE_SSL_CERT", "SOURCE_SSL_CIPHER", "SOURCE_SSL_CRL", "SOURCE_SSL_CRLPATH", "SOURCE_SSL_KEY", "SOURCE_SSL_VERIFY_SERVER_CERT", "SOURCE_TLS_CIPHERSUITES", "SOURCE_TLS_VERSION", "SOURCE_USER", "SOURCE_ZSTD_COMPRESSION_LEVEL", "SPATIAL", "SPECIFIC", "SQL", "SQLEXCEPTION", "SQLSTATE", "SQLWARNING", "SRID", "SQL_AFTER_GTIDS", "SQL_AFTER_MTS_GAPS", "SQL_BEFORE_GTIDS", "SQL_BIG_RESULT", "SQL_BUFFER_RESULT", "SQL_CACHE", "SQL_CALC_FOUND_ROWS", "SQL_NO_CACHE", "SQL_SMALL_RESULT", "SQL_THREAD", "SQL_TSI_DAY", "SQL_TSI_HOUR", "SQL_TSI_MINUTE", "SQL_TSI_MONTH", "SQL_TSI_QUARTER", "SQL_TSI_SECOND", "SQL_TSI_WEEK", "SQL_TSI_YEAR", "SSL", "STACKED", "START", "STARTING", "STARTS", "STATS_AUTO_RECALC", "STATS_PERSISTENT", "STATS_SAMPLE_PAGES", "STATUS", "STOP", "STORAGE", "STORED", "STRAIGHT_JOIN", "STREAM", "STRING", "SUBCLASS_ORIGIN", "SUBJECT", "SUBPARTITION", "SUBPARTITIONS", "SUPER", "SUSPEND", "SWAPS", "SWITCHES", "SYSTEM", "TABLE", "TABLES", "TABLESPACE", "TABLE_CHECKSUM", "TABLE_NAME", "TEMPORARY", "TEMPTABLE", "TERMINATED", "TEXT", "THAN", "THEN", "THREAD_PRIORITY", "TIES", "TIME", "TIMESTAMP", "TIMESTAMPADD", "TIMESTAMPDIFF", "TINYBLOB", "TINYINT", "TINYTEXT", "TLS", "TO", "TRAILING", "TRANSACTION", "TRIGGER", "TRIGGERS", "TRUE", "TRUNCATE", "TYPE", "TYPES", "UNBOUNDED", "UNCOMMITTED", "UNDEFINED", "UNDO", "UNDOFILE", "UNDO_BUFFER_SIZE", "UNICODE", "UNINSTALL", "UNION", "UNIQUE", "UNKNOWN", "UNLOCK", "UNREGISTER", "UNSIGNED", "UNTIL", "UPDATE", "UPGRADE", "USAGE", "USE", "USER", "USER_RESOURCES", "USE_FRM", "USING", "UTC_DATE", "UTC_TIME", "UTC_TIMESTAMP", "VALIDATION", "VALUE", "VALUES", "VARBINARY", "VARCHAR", "VARCHARACTER", "VARIABLES", "VARYING", "VCPU", "VIEW", "VIRTUAL", "VISIBLE", "WAIT", "WARNINGS", "WEEK", "WEIGHT_STRING", "WHEN", "WHERE", "WHILE", "WINDOW", "WITH", "WITHOUT", "WORK", "WRAPPER", "WRITE", "X509", "XA", "XID", "XML", "XOR", "YEAR", "YEAR_MONTH", "ZEROFILL", "ZONE"));

    public DmKeyWordsHandler(){
        super(new HashSet(KEY_WORDS));
    }

    @Override
    public @NotNull String formatStyle() {
        return "%s";
    }

}

4、启动类

package com.camp.gen;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.camp.gen.config.GeneratorConfig;
import com.camp.gen.handler.MyFreeMarkerTemplateEngine;
import java.util.*;


/**
 * @Description 代码生成器
 * @Author HS
 * @Date 2022/11/27 16:23
 */
public class MyGenerator {

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator(GeneratorConfig.initDataSourceConfig());
        //自定义参数,全局适用
        HashMap parameterMap = new HashMap<>(4);
        parameterMap.put("workflow", true);
        parameterMap.put("permission", true);
        //需要生成的表名
        List tableLists = Arrays.asList("SW_FORM");
        //全局配置
        mpg.global(GeneratorConfig.initGlobalConfig())
                //包配置
                .packageInfo(GeneratorConfig.initPackageConfig())
                //模板配置
                .template(GeneratorConfig.initTemplateConfig())
                //策略配置
                .strategy(GeneratorConfig.initStrategyConfig(tableLists))
                //自定义配置
                .injection(GeneratorConfig.initInjectionConfig(parameterMap));
        //生成
        mpg.execute(new MyFreeMarkerTemplateEngine());
    }

}

5、模板

目录结构

Mybatis-Plus代码生成器详解及完整代码实现_第2张图片

5.1 controller.java.ftl

package ${package.Controller};


import org.springframework.web.bind.annotation.RequestMapping;

<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;

<#if superControllerClassPackage??>
import ${superControllerClassPackage};

import ${package.Service}.${table.serviceName};
import com.css.cssbase.base.annotation.OperateLog;
import com.css.cssbase.base.model.ResponseData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.util.CollectionUtils;
<#if permission>
import org.apache.shiro.authz.annotation.RequiresPermissions;




/**
 * 

* ${table.comment!}前端控制器 *

* * @author ${author} * @since ${date} */ <#if restControllerStyle> @RestController <#else> @Controller @RequestMapping("<#if package.ModuleName!?length gt 0>/${package.ModuleName}/<#if controllerMappingHyphenStyle>${controllerMappingHyphen}<#else>${table.entityPath}") <#if kotlin> class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}() <#else> <#if superControllerClass??> public class ${table.controllerName} extends ${superControllerClass} { <#else> public class ${table.controllerName} { <#if table.serviceName??> @Autowired private ${table.serviceName} ${table.serviceName?uncap_first}; <#--- controller方法 start ---> @PostMapping <#if permission> @RequiresPermissions("${table.entityPath}:add") @OperateLog("保存${table.comment!}") public ResponseData add${entity}(@RequestBody ${entity}DTO ${entity?uncap_first}DTO){ return ResponseData.builder().data("data",${table.serviceName?uncap_first}.add${entity}(${entity?uncap_first}DTO)).build(); } @GetMapping("/{id}") <#if permission> @RequiresPermissions("${table.entityPath}:get") @OperateLog("查看${table.comment!}") public ResponseData get${entity}(@PathVariable Long id){ return ResponseData.builder().data("data",${table.serviceName?uncap_first}.get${entity}(id)).build(); } @PutMapping <#if permission> @RequiresPermissions("${table.entityPath}:update") @OperateLog("更新${table.comment!}") public ResponseData upd${entity}(@RequestBody ${entity}DTO ${entity?uncap_first}DTO){ return ResponseData.builder().data("data",${table.serviceName?uncap_first}.upd${entity}(${entity?uncap_first}DTO)).build(); } @DeleteMapping <#if permission> @RequiresPermissions("${table.entityPath}:delete") @OperateLog("删除${table.comment!}") public ResponseData del${entity}(@RequestParam List ids){ if(!CollectionUtils.isEmpty(ids)){ ${table.serviceName?uncap_first}.del${entity}(ids); } return ResponseData.builder().build(); } <#--- controller方法 end ---> }

5.2entity.java.ftl

package ${package.Entity};

<#list table.importPackages as pkg>
import ${pkg};

<#if entityLombokModel>
import lombok.Data;
    <#if chainModel>
import lombok.experimental.Accessors;
    

<#--- 流程相关 -->
<#if workflow>
import com.css.cssbase.moudles.flowbase.model.FlowBase;


/**
 * 

* ${table.comment!} *

* * @author ${author} * @since ${date} */ <#if entityLombokModel> @Data <#if table.convert> @TableName("${table.name}") <#if superEntityClass??> public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}> implements Serializable { <#elseif activeRecord> public class ${entity} extends Model<${entity}> implements Serializable { <#else> public class ${entity} <#if workflow>extends FlowBase implements Serializable { <#if entitySerialVersionUID> private static final long serialVersionUID = 1L; <#-- ---------- BEGIN 字段循环遍历 ----------> <#list table.fields as field> <#if field.keyFlag> <#assign keyPropertyName="${field.propertyName}"/> <#if field.comment!?length gt 0> /** * ${field.comment} */ <#if field.keyFlag> <#-- 主键 --> <#if field.keyIdentityFlag> @TableId(value = "${field.columnName}", type = IdType.AUTO) <#elseif idType??> @TableId(value = "${field.columnName}", type = IdType.${idType}) <#elseif field.convert> @TableId("${field.columnName}") <#-- 普通字段 --> <#elseif field.fill??> <#-- ----- 存在字段填充设置 -----> <#if field.convert> @TableField(value = "${field.columnName}", fill = FieldFill.${field.fill}) <#else> @TableField(fill = FieldFill.${field.fill}) <#elseif field.convert> @TableField("${field.columnName}") <#-- 乐观锁注解 --> <#if (versionFieldName!"") == field.name> @Version <#-- 逻辑删除注解 --> <#if (logicDeleteFieldName!"") == field.name> @TableLogic private ${field.propertyType} ${field.propertyName}; <#------------ END 字段循环遍历 ----------> <#if !entityLombokModel> <#list table.fields as field> <#if field.propertyType == "boolean"> <#assign getprefix="is"/> <#else> <#assign getprefix="get"/> public ${field.propertyType} ${getprefix}${field.capitalName}() { return ${field.propertyName}; } <#if chainModel> 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 chainModel> return this; } <#if entityColumnConstant> <#list table.fields as field> public static final String ${field.name?upper_case} = "${field.name}"; <#if activeRecord> @Override protected Serializable pkVal() { <#if keyPropertyName??> return this.${keyPropertyName}; <#else> return null; } <#if !entityLombokModel> @Override public String toString() { return "${entity}{" + <#list table.fields as field> <#if field_index==0> "${field.propertyName}=" + ${field.propertyName} + <#else> ", ${field.propertyName}=" + ${field.propertyName} + "}"; } }

5.3 service.java.ftl

package ${package.Service};

import ${package.Entity}.${entity};
import ${superServiceClassPackage};

/**
 * 

* ${table.comment!}服务类 *

* * @author ${author} * @since ${date} */ <#if kotlin> interface ${table.serviceName} : ${superServiceClass}<${entity}> <#else> public interface ${table.serviceName} extends ${superServiceClass}<${entity}> { /** * 保存${table.comment!} * @param ${entity}DTO */ ${entity}VO add${entity}(${entity}DTO ${entity?uncap_first}DTO); /** * 查看${table.comment!} * @param id */ ${entity}VO get${entity}(Long id); /** * 更新${table.comment!} * @param ${entity}DTO */ ${entity}VO upd${entity}(${entity}DTO ${entity?uncap_first}DTO); /** * 删除${table.comment!} * @param ids */ void del${entity}(List ids); }

5.4 serviceImpl.java.ftl

package ${package.ServiceImpl};

import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;

/**
 * 

* ${table.comment!}服务实现类 *

* * @author ${author} * @since ${date} */ @Service <#if kotlin> open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} { } <#else> public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} { @Autowired private ${table.mapperName} ${table.mapperName?uncap_first} /** * 保存${table.comment!} * @param ${entity}DTO */ @Override public ${entity}VO add${entity}(${entity}DTO ${entity?uncap_first}DTO){ ${entity} ${entity?uncap_first} = new ${entity}(); BeanUtils.copyProperties(${entity?uncap_first}DTO, ${entity?uncap_first}); //属性初始化 //插入操作 //返回VO return new ${entity}VO(); } /** * 查看${table.comment!} * @param id */ @Override public ${entity}VO get${entity}(Long id){ } /** * 更新${table.comment!} * @param ${entity}DTO */ @Override public ${entity}VO upd${entity}(${entity}DTO ${entity?uncap_first}DTO){ } /** * 删除${table.comment!} * @param ids */ @Override public void del${entity}(List ids){ } }

5.5 mapper.java.ftl

package ${package.Mapper};

import ${package.Entity}.${entity};
import ${superMapperClassPackage};
import org.springframework.stereotype.Repository;
<#if enableCache>
import org.mybatis.caches.memcached.MemcachedCache;
import org.apache.ibatis.annotations.CacheNamespace;

/**
 * 

* ${table.comment!}Mapper接口 *

* * @author ${author} * @since ${date} */ @Repository <#if enableCache> @CacheNamespace(implementation = MemcachedCache.class) <#if kotlin> interface ${table.mapperName} : ${superMapperClass}<${entity}> <#else> public interface ${table.mapperName} extends ${superMapperClass}<${entity}> { }

5.6 mapper.xml.ftl




<#if enableCache>
    
    


<#if baseResultMap>
    
    
<#list table.fields as field>
<#if field.keyFlag><#--生成主键排在第一位-->
        


<#list table.commonFields as field><#--生成公共字段 -->
        

<#list table.fields as field>
<#if !field.keyFlag><#--生成普通字段 -->
        


    


<#if baseColumnList>
    
    
<#list table.commonFields as field>
        ${field.columnName},

        ${table.fieldNames}
    




5.7 dto.java.ftl

package ${package.Other};

<#list table.importPackages as pkg>
import ${pkg};

<#if entityLombokModel>
import lombok.Data;
    <#if chainModel>
import lombok.experimental.Accessors;
    


/**
 * 

* ${table.comment!} *

* * @author ${author} * @since ${date} */ <#if entityLombokModel> @Data <#if superEntityClass??> public class ${entity}DTO extends ${superEntityClass}<#if activeRecord><${entity}> implements Serializable { <#elseif activeRecord> public class ${entity}DTO extends Model<${entity}> implements Serializable { <#else> public class ${entity}DTO implements Serializable { <#if entitySerialVersionUID> private static final long serialVersionUID = 1L; <#-- ---------- BEGIN 字段循环遍历 ----------> <#list table.fields as field> <#if field.comment!?length gt 0> /** * ${field.comment} */ private ${field.propertyType} ${field.propertyName}; <#------------ END 字段循环遍历 ----------> }

5.8 vo.java.ftl

package ${package.Other};

<#list table.importPackages as pkg>
import ${pkg};

<#if entityLombokModel>
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
    <#if chainModel>
import lombok.experimental.Accessors;
    


/**
 * 

* ${table.comment!} *

* * @author ${author} * @since ${date} */ <#if entityLombokModel> @Data @NoArgsConstructor @AllArgsConstructor <#if superEntityClass??> public class ${entity}VO extends ${superEntityClass}<#if activeRecord><${entity}> implements Serializable { <#elseif activeRecord> public class ${entity}VO extends Model<${entity}> implements Serializable { <#else> public class ${entity}VO implements Serializable { <#if entitySerialVersionUID> private static final long serialVersionUID = 1L; <#-- ---------- BEGIN 字段循环遍历 ----------> <#list table.fields as field> <#if field.comment!?length gt 0> /** * ${field.comment} */ private ${field.propertyType} ${field.propertyName}; <#------------ END 字段循环遍历 ----------> }

你可能感兴趣的:(mybatis,spring,boot,mysql)