最详细的mybatis plus代码生成配置–自定义生成代码路径并生成扩展类–高级配置

最详细的mybatis plus代码生成配置–自定义生成代码路径并生成扩展类–高级配置Mybatisplus 号称是只做增强不做改变 可快速进行单表 CRUD 操作 从而节省大量时间 具备代码生成 物理分页 性能分析等功能 官网地址教程地址 https baomidou com guide PS 其实 mybatis 本身就可以自动生成一些常用代码和单表查询的语句 只是没有 mp 功能这么多而已 不过 快速开发的时候 mp 还是很给力的 背景 项目中 采用了 springboot 框架 集成 mybatisplus 的时候 有很多不如意的地方 于是就游走与官网和社区中 仓促写了个代

Mybatis plus 号称是只做增强不做改变,可快速进行单表 CRUD 操作,从而节省大量时间,具备代码生成、物理分页、性能分析等功能,官网地址教程地址 https://baomidou.com/guide/ 

PS:其实mybatis本身就可以自动生成一些常用代码和单表查询的语句,只是没有mp功能这么多而已,不过,快速开发的时候mp还是很给力的。

 背景:

项目中,采用了springboot框架,集成mybatis plus的时候,有很多不如意的地方,于是就游走与官网和社区中,仓促写了个代码生成器,以备后用  

项目依赖 

 
   
   
   
     com.study.common 
    
   
     common 
    
   
     1.0.0 
    
   
   
   
   
     com.github.xiaoymin 
    
   
     knife4j-spring-boot-starter 
    
   
     2.0.1 
    
    
     
     
       guava 
      
     
       com.google.guava 
      
     
    
   
   
   
     org.springframework.boot 
    
   
     spring-boot-starter 
    
   
   
   
   
     org.apache.velocity 
    
   
     velocity-engine-core 
    
   
     2.1 
    
   
   
   
   
     mysql 
    
   
     mysql-connector-java 
    
   
   
   
     org.springframework.boot 
    
   
     spring-boot-starter-test 
    
   
     test 
    
    
     
     
       org.junit.vintage 
      
     
       junit-vintage-engine 
      
     
    
   
   
   
   
     org.projectlombok 
    
   
     lombok 
    
   
     true 
    
   
   
   
   
     com.baomidou 
    
   
     mybatis-plus-generator 
    
   
     3.4.0 
    
  

 配置

 全局配置

  • 设置代码生成后是否打开生成代码所在目录
  • 设置是否要覆盖同名文件
  • 设置XML中是否要生成ResultMap映射(就是MybatisPlus默认给你当前表所有字段的ResultMap)
  • 设置是否生成基本的表字段的视图(就是 id,…)
  • 设置是否需要Swagger注解(就是@ApiOperation注解,用来生成文档)
  • 设置作者名,用于类注释和方法注释
  • 设置生成类的别名(如%sDao表示原来的类名后面跟上Dao)
 / * 全局配置 * * @return */ private static GlobalConfig globalConfig() { return new GlobalConfig() // 打开文件 .setOpen(false) // 文件覆盖 .setFileOverride(true) // 开启activeRecord模式 .setActiveRecord(false) // XML ResultMap: mapper.xml生成查询映射结果 .setBaseResultMap(true) // XML ColumnList: mapper.xml生成查询结果列 .setBaseColumnList(true) // swagger注解; 须添加swagger依赖 .setSwagger2(true) // 作者 .setAuthor(AUTHOR) // 设置实体类名称 .setEntityName("%sDO") //设置服务类名称 .setServiceName("%sService") ; }

 数据源配置

这个相对比较简单

 / * 数据源配置 * * @return */ private static DataSourceConfig dataSourceConfig() { return new DataSourceConfig() // 数据库类型 .setDbType(DB_TYPE) // 连接驱动 .setDriverName(driverClassName) // 地址 .setUrl(url) // 用户名 .setUsername(username) // 密码 .setPassword(password); }

 配置文件策略

  • 设置表名和表字段生成策略(由于数据库中通常都是下划线命名,但是Java中通常是驼峰命名,所以通常会配置下划线转驼峰的配置)
  • 设置需要生成代码的表
  • 设置生成代码时需要去掉的前缀(因为表中常常会有前缀 info_ dict_ relation_ 之类特殊含义的前缀,可以按需调整)
  • 设置是否需要Lombok注解
  • 设置是否需要构建者模式
  • 设置是否需要生成表信息注解
  • 设置特殊意义字段
    • 逻辑删除
    • 自动更新插入
    • 版本迭代字段
  • 设置父类中字段
    • 如 id version deleted类似的字段几乎是每一张表都会有的字段,这样就可以设置一个共同的父类来保存这些字段
  • 设置父类,也就是某个类需要继承的类
 / * 设置表格/字段等生成策略配置 * * @return */ private static StrategyConfig strategyConfig() { StrategyConfig strategyConfig = new StrategyConfig() // 表名生成策略:下划线连转驼峰 .setNaming(NamingStrategy.underline_to_camel) // 表字段生成策略:下划线连转驼峰 .setColumnNaming(NamingStrategy.underline_to_camel) // 需要生成的表 .setInclude(TABLES) // 生成controller .setRestControllerStyle(true) // 去除表前缀 .setTablePrefix(ENTITY_IGNORE_PREFIX) // controller映射地址:驼峰转连字符 .setControllerMappingHyphenStyle(false) // 是否启用builder 模式 .setChainModel(true) // 是否为lombok模型; 需要lombok依赖 .setEntityLombokModel(true) // 生成实体类字段注解 .setEntityTableFieldAnnotationEnable(true) // 乐观锁、逻辑删除、表填充 // .setVersionFieldName("version") .setLogicDeleteFieldName("is_deleted") .setTableFillList(Arrays.asList( new TableFill("gmt_modified", FieldFill.UPDATE), new TableFill("gmt_create", FieldFill.INSERT) )) // 生成类的时候排除的字符串(因为这些字段已经在父类中,子类无需再生成) .setSuperEntityColumns( SUPER_ENTITY_COLUMNS ); //配置父类 if (Objects.nonNull(SUPER_ENTITY_CLASS) && SUPER_ENTITY_CLASS.length() > 0) { strategyConfig.setSuperEntityClass(SUPER_ENTITY_CLASS); } return strategyConfig; }

PS : 至此,使用mybatis plus官方模版已经可以生成自动代码了,不过生成的代码并不符合我的要求。我需要自定义生成文件的路劲和自定义生成类  

建表语句 

SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for shop_order -- ---------------------------- DROP TABLE IF EXISTS `shop_order`; CREATE TABLE `shop_order` ( `id` int(11) NOT NULL, `mount` decimal(20, 0) NULL DEFAULT NULL COMMENT '金额', `status` tinyint(1) NOT NULL COMMENT '状态 0:未支付 1:已经支付', `importance` tinyint(5) UNSIGNED NULL DEFAULT 0 COMMENT '排序字段', `creator` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', `modifier` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', `gmt_create` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', `gmt_modified` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', `is_deleted` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '是否被删除 1:数据无效(被删除) 0:数据有效', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;

 BaseDO实体 

package com.study.common.entity; import com.baomidou.mybatisplus.annotation.*; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.util.Date; / * @Package: com.study.common.entity * @Description: 
  <基础实体类>
    * @Author: milla * @CreateDate: 2020/11/06 14:56 * @UpdateUser: milla * @UpdateDate: 2020/11/06 14:56 * @UpdateRemark: <> * @Version: 1.0 */ @ApiModel(value = "基础实体") @Data public abstract class BaseDO implements Serializable { / * 序列化时候使用 */ private static final long serialVersionUID = 1L; / * 排序字段 */ @ApiModelProperty(value = "排序字段", notes = "默认按照记录id正序输出") @TableField(fill = FieldFill.INSERT_UPDATE, update = "12") private Integer importance; / * 创建人 */ @ApiModelProperty(value = "创建人", notes = "") private String creator; / * 修改人 */ @ApiModelProperty(value = "修改人", notes = "") private String modifier; / * 数据创建时间 */ @ApiModelProperty(value = "数据创建时间", notes = "") @TableField(fill = FieldFill.INSERT) private Date gmtCreate; / * 数据被修改时间 */ @ApiModelProperty(value = "数据被修改时间", notes = "") @TableField(fill = FieldFill.INSERT_UPDATE) private Date gmtModified; @TableLogic / * 数据是否被删除 */ @ApiModelProperty(value = "数据是否被删除", notes = "逻辑删除字段") protected Integer isDeleted; @TableId(value = "id", type = IdType.AUTO) / *主键自增 */ @ApiModelProperty(value = "主键自增", notes = "") protected Long id; } 
  

 QueryBO-查询实体

package com.study.common.entity.bo; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; / * @Package: com.study.common.entity.bo * @Description: 
  <查询实体类>
    * @Author: milla * @CreateDate: 2020/11/06 14:56 * @UpdateUser: milla * @UpdateDate: 2020/11/06 14:56 * @UpdateRemark: <> * @Version: 1.0 */ @Data @ApiModel(value = "查询实体类") public class QueryBO 
   
     { @ApiModelProperty(value = "分页实体", notes = "包含分页参数") private Page 
    
      page; @ApiModelProperty(value = "实体参数", notes = "") private T entity; public QueryWrapper initQueryWrapper() { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.setEntity(entity); return wrapper; } } 
     
    
  

 常量类

 BasicConstant

主要用于配置表格和数据库信息

package com.study.generator; import com.baomidou.mybatisplus.annotation.DbType; / * @Package: com.study.generator * @Description: 
  <表格和数据源配置项>
    * @Author: milla * @CreateDate: 2020/11/12 17:48 * @UpdateUser: milla * @UpdateDate: 2020/11/12 17:48 * @UpdateRemark: <> * @Version: 1.0 */ public final class BasicConstant { / * 作者 */ public static String AUTHOR = "milla" ; / * 生成的实体类忽略表前缀: 不需要则置空 */ public static String ENTITY_IGNORE_PREFIX = "settings_" ; / * 表名 */ public static String[] TABLES = { "shop_order" }; / * 实体类的父类Entity */ public static String SUPER_ENTITY_CLASS = "com.aimsphm.nuclear.common.entity.BaseDO" ; / * 基础父类继承字段 */ public static String[] SUPER_ENTITY_COLUMNS = { "id", "creator", "modifier", "gmt_modified", "gmt_create", "is_deleted", "importance" }; / * 数据库 */ public static String username = "root" ; public static String password = "*" ; public static String url = "jdbc:mysql://192.168.1.1:3306/test?useAffectedRows=true&allowMultiQueries=true&characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false&maxReconnects=10" ; public static DbType DB_TYPE = DbType.MYSQL; public static String driverClassName = "com.mysql.cj.jdbc.Driver" ; } 
  

 PackageInfoConstant

– 主要用来配置文件生成路径及java类的包路径

package com.study.generator; import java.io.File; / * @Package: com.study.generator * @Description: 
  <自定义生成的文件路径和包路径>
    * @Author: milla * @CreateDate: 2020/11/12 17:47 * @UpdateUser: milla * @UpdateDate: 2020/11/12 17:47 * @UpdateRemark: <> * @Version: 1.0 */ public final class PackageInfoConstant { //------------------------------可能需要修改的配置--------------------------------------------- / * ------------------------------controller层单独配置-------------------------- */ public static String CONTROLLER_OUTPUT_ROOT_PATH = "/com/study/" ; / * controller根目录 */ public static String ROOT_PROJECT_CONTROLLER_PATH = "/core" ; / * 包路径(基础包路径) */ public static String PACKAGE_ROOT = "com.study" ; / * Controller模块(笔者的controller和service,dao,entity不在同一个项目中) */ public static String CONTROLLER_MODULE_NAME = "core" ; / * controller的包路径 */ public static String PACKAGE_CONTROLLER = PACKAGE_ROOT + "." + CONTROLLER_MODULE_NAME + ".controller" ; / * ------------------------------controller以外的其他配置-------------------------- */ / * 根路径 */ public static String ROOT_PROJECT_PATH = "/common" ; / * 输出基础包 */ public static String OUTPUT_ROOT_PATH = "/com/study/" ; / * 配置你包路径下的子模块(例如:com.study.common) * (例如:com.study.ext) */ public static String MODULE_NAME = "common" ; / * 扩展模块 */ public static String EXT_MODULE_NAME = "ext" ; public static String PACKAGE_PARENT = PACKAGE_ROOT + "." + MODULE_NAME; / * 扩展基础包路径 */ public static String PACKAGE_PARENT_EXT = PACKAGE_ROOT + "." + EXT_MODULE_NAME; //--------------------------------------------------------------------------- / * 扩展的实体名称 */ public static String EXT_ClASS_NAME = "Ext" ; / * 扩展实现类名称 */ public static String EXT_SERVICE_CLASSNAME_IMPL = "ExtImpl" ; / * 生成文件路径、Dao、XML、Service、Controller * 父包名路径(文件输出路径,也是导包的路径) */ public static String ENTITY_PATH = "/entity/" ; public static String MAPPER_PATH = "/mapper/" ; public static String XML_PATH = "/resources/mapper/" ; public static String XML_PATH_EXT = "/resources/mapper/ext/" ; public static String SERVICE_PATH = "/service/" ; public static String SERVICE_IMPL_PATH = "/service/impl/" ; public static String CONTROLLER_PATH = "/controller/" ; public static String MAIN_ROOT = "/src/main/" ; public static String JAVA_ROOT = MAIN_ROOT + "/java/" ; / * 包路径中的mapper,service,impl等常量 */ public static String PACKAGE_NAME_MAPPER = "mapper" ; public static String PACKAGE_NAME_SERVICE = "service" ; public static String PACKAGE_NAME_IMPL = "impl" ; / * mapper.xml输出模块路径(需要注意放置的位置:默认从模块/src/main下开始) */ public static String XML_OUTPUT_MODULE = File.separator + MODULE_NAME; public static String XML_OUTPUT_PATH = ROOT_PROJECT_PATH + MAIN_ROOT + XML_PATH; / * IService.java, serviceImpl.java输出模块路径 */ public static String SERVICE_OUTPUT_MODULE = File.separator + MODULE_NAME; public static String SERVICE_OUTPUT_PATH = ROOT_PROJECT_PATH + JAVA_ROOT + OUTPUT_ROOT_PATH + SERVICE_OUTPUT_MODULE + SERVICE_PATH; public static String SERVICE_IMPL_OUTPUT_PATH = ROOT_PROJECT_PATH + JAVA_ROOT + OUTPUT_ROOT_PATH + SERVICE_OUTPUT_MODULE + SERVICE_IMPL_PATH; / * Entity.java, Mapper.java, Mapper.xml输出模块路径 */ public static String DAO_OUTPUT_MODULE = File.separator + MODULE_NAME; public static String ENTITY_OUTPUT_PATH = ROOT_PROJECT_PATH + JAVA_ROOT + OUTPUT_ROOT_PATH + DAO_OUTPUT_MODULE + ENTITY_PATH; public static String MAPPER_OUTPUT_PATH = ROOT_PROJECT_PATH + JAVA_ROOT + OUTPUT_ROOT_PATH + DAO_OUTPUT_MODULE + MAPPER_PATH; / * ----------------------------------------EXT_CONFIG---------------------------------------------------- */ / * mapper.xml输出模块路径(需要注意放置的位置:默认从模块/src/main下开始) */ public static String XML_OUTPUT_PATH_EXT = ROOT_PROJECT_PATH + MAIN_ROOT + XML_PATH_EXT; / * IService.java, serviceImpl.java输出模块路径 */ public static String SERVICE_OUTPUT_MODULE_EXT = File.separator + EXT_MODULE_NAME; public static String SERVICE_OUTPUT_PATH_EXT = ROOT_PROJECT_PATH + JAVA_ROOT + OUTPUT_ROOT_PATH + SERVICE_OUTPUT_MODULE_EXT + SERVICE_PATH; public static String SERVICE_IMPL_OUTPUT_PATH_EXT = ROOT_PROJECT_PATH + JAVA_ROOT + OUTPUT_ROOT_PATH + SERVICE_OUTPUT_MODULE_EXT + SERVICE_IMPL_PATH; / * Entity.java, Mapper.java, Mapper.xml输出模块路径 */ public static String DAO_OUTPUT_MODULE_EXT = File.separator + EXT_MODULE_NAME; public static String MAPPER_OUTPUT_PATH_EXT = ROOT_PROJECT_PATH + JAVA_ROOT + OUTPUT_ROOT_PATH + DAO_OUTPUT_MODULE_EXT + MAPPER_PATH; / * ----------------------------------------EXT_CONFIG---------------------------------------------------- */ / * Controller.java输出模块路径 */ public static String CONTROLLER_OUTPUT_MODULE = File.separator + CONTROLLER_MODULE_NAME; public static String CONTROLLER_OUTPUT_PATH = ROOT_PROJECT_CONTROLLER_PATH + JAVA_ROOT + CONTROLLER_OUTPUT_ROOT_PATH + CONTROLLER_OUTPUT_MODULE + CONTROLLER_PATH; } 
  

TemplateConstant

– 主要用来配置模版位置

package com.study.generator; / * @Package: com.study.generator * @Description: 
  <模版位置配置类>
    * @Author: milla * @CreateDate: 2020/11/12 18:09 * @UpdateUser: milla * @UpdateDate: 2020/11/12 18:09 * @UpdateRemark: <> * @Version: 1.0 */ public final class TemplateConstant { / * entity输出模板 */ public static String ENTITY_TEMPLATE = "templates/entity.java.vm" ; / * mapper.xml输出模板 */ public static String XML_TEMPLATE = "templates/mapper.xml.vm" ; / * mapper.java输出模板 */ public static String MAPPER_TEMPLATE = "templates/mapper.java.vm" ; / * service输出模板 */ public static String SERVICE_TEMPLATE = "templates/service.java.vm" ; / * serviceImpl输出模板 */ public static String SERVICE_IMPL_TEMPLATE = "templates/serviceImpl.java.vm" ; / * mapperExt.xml输出模板 */ public static String XML_TEMPLATE_EXT = "templates/mapperExt.xml.vm" ; / * mapperExt.java输出模板 */ public static String MAPPER_TEMPLATE_EXT = "templates/mapperExt.java.vm" ; / * serviceExt输出模板 */ public static String SERVICE_TEMPLATE_EXT = "templates/serviceExt.java.vm" ; / * serviceExtImpl输出模板 */ public static String SERVICE_IMPL_TEMPLATE_EXT = "templates/serviceExtImpl.java.vm" ; / * controller输出模板 */ public static String CONTROLLER_TEMPLATE = "templates/controller.java.vm" ; } 
  

 模版配置

– 因为要生成entity,mapper,mapperExt,mapper.xml,mapperExt.xml,service,serviceExt,serviceImpl,serviceIExtmpl,controller

– 所以会有多个模版

 entity.java.vm

package ${package.Entity}; #foreach($pkg in ${table.importPackages}) import ${pkg}; #end import lombok.Data; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; / * @Package: ${package.Entity} * @Description: <$!{table.comment}实体> * @Author: ${author} * @CreateDate: ${date} * @UpdateUser: ${author} * @UpdateDate: ${date} * @UpdateRemark: <> * @Version: 1.0 */ @Data #if(${cfg.customerTableName}) @TableName("${table.name}") #end #if(${swagger2}) @ApiModel(value = "$!{table.comment}实体") #end #if(${superEntityClass}) public class ${entity} extends ${superEntityClass}#if(${activeRecord})<${entity}>#end { #else public class ${entity} implements Serializable{ #end / * 序列化时候使用 */ private static final long serialVersionUID = ${cfg.get(${table.name})}L; ---------- BEGIN 字段循环遍历 ---------- #foreach($field in ${table.fields}) #if(${field.keyFlag}) #set($keyPropertyName=${field.propertyName}) #end if("$!field.comment" != "") / * ${field.comment} */ end #if(${field.keyFlag}) 主键 #if(${field.keyIdentityFlag}) @TableId(value = "${field.name}", type = IdType.AUTO) #elseif(${field.convert}) @TableId("${field.name}") #end #end 乐观锁注解 #if(${versionFieldName}==${field.name}) @Version #end 逻辑删除注解 #if(${logicDeleteFieldName}==${field.name}) @TableLogic #end 生成swagg实体描述 #if(${swagger2}) #set($comment=${field.comment}) #set($blankIndex=$comment.indexOf(" ")) #set($hasBlank=$comment.indexOf(" ")!=-1) #if($hasBlank) @ApiModelProperty(value = "$comment.substring(0,$blankIndex)", notes = "$comment.substring($blankIndex).trim()") #end #if(!$hasBlank) @ApiModelProperty(value = "$comment", notes = "") #end #end private ${field.propertyType} ${field.propertyName}; #end }

 mapper.java.vm

package ${package.Mapper}; import ${package.Entity}.${entity}; import ${superMapperClassPackage}; / * @Package: ${package.Mapper} * @Description: <$!{table.comment}Mapper接口> * @Author: ${author} * @CreateDate: ${date} * @UpdateUser: ${author} * @UpdateDate: ${date} * @UpdateRemark: <> * @Version: 1.0 */ #if(${kotlin}) interface ${table.mapperName} : ${superMapperClass}<${entity}> #else public interface ${table.mapperName} extends ${superMapperClass}<${entity}> { } #end

mapperExt.java.vm

package ${cfg.extPackagePre}.${cfg.mapper}; import ${package.Mapper}.${table.mapperName}; / * @Package: ${cfg.extPackagePre}.${cfg.mapper} * @Description: <$!{table.comment}MapperExt接口> * @Author: ${author} * @CreateDate: ${date} * @UpdateUser: ${author} * @UpdateDate: ${date} * @UpdateRemark: <> * @Version: 1.0 */ #if(${kotlin}) interface ${table.mapperName}${cfg.classNameExt} : ${superMapperClass}<${entity}> #else public interface ${table.mapperName}${cfg.classNameExt} extends ${table.mapperName} { } #end

 mapper.xml.vm

 
   
  
    #if(${enableCache}) 
    
    #end #if(${baseResultMap}) 
    
   
     #foreach($field in ${table.fields}) #if(${field.keyFlag})生成主键排在第一位 
     #end #end #foreach($field in ${table.commonFields})生成公共字段 
     #end #foreach($field in ${table.fields}) #if(!${field.keyFlag})生成普通字段 
     #end #end 
    #end #if(${baseColumnList}) 
    
   
     #foreach($field in ${table.commonFields}) ${field.columnName}, #end ${table.fieldNames} 
    #end 
  

 mapperExt.xml.vm

 
   
  
    #if(${enableCache}) 
    
    #end #if(${baseResultMap}) 
    
    
    #end #if(${baseColumnList}) 
    
   
     #foreach($field in ${table.commonFields}) ${field.columnName}, #end ${table.fieldNames} 
    #end 
  

service.java.vm

package ${package.Service}; import ${package.Entity}.${entity}; import ${superServiceClassPackage}; / * @Package: ${package.Service} * @Description: <$!{table.comment}服务类> * @Author: ${author} * @CreateDate: ${date} * @UpdateUser: ${author} * @UpdateDate: ${date} * @UpdateRemark: <> * @Version: 1.0 */ #if(${kotlin}) interface ${table.serviceName} : ${superServiceClass}<${entity}> #else public interface ${table.serviceName} extends ${superServiceClass}<${entity}> { } #end 

 serviceExt.java.vm

package ${cfg.extPackagePre}.${cfg.service}; import ${package.Service}.${table.serviceName}; / * @Package: ${cfg.extPackagePre}.${cfg.service} * @Description: <$!{table.comment}扩展服务类> * @Author: ${author} * @CreateDate: ${date} * @UpdateUser: ${author} * @UpdateDate: ${date} * @UpdateRemark: <> * @Version: 1.0 */ #if(${kotlin}) interface ${table.serviceName}${cfg.classNameExt} : ${table.serviceName} #else public interface ${table.serviceName}${cfg.classNameExt} extends ${table.serviceName} { } #end 

serviceImpl.java.vm

package ${package.ServiceImpl}; import ${package.Entity}.${entity}; import ${package.Mapper}.${table.mapperName}; import ${package.Service}.${table.serviceName}; import ${superServiceImplClassPackage}; import org.springframework.stereotype.Service; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; / * @Package: ${package.ServiceImpl} * @Description: <$!{table.comment}服务实现类> * @Author: ${author} * @CreateDate: ${date} * @UpdateUser: ${author} * @UpdateDate: ${date} * @UpdateRemark: <> * @Version: 1.0 */ @Service #if(${kotlin}) open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} { } #else @ConditionalOnProperty(prefix = "spring.config-service", name = "enable", havingValue = "true", matchIfMissing = false) public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} { } #end

 serviceExtImpl.java.vm

package ${cfg.extPackagePre}.${cfg.service}.${cfg.serviceImpl}; import ${cfg.extPackagePre}.${cfg.service}.${table.serviceName}${cfg.classNameExt}; import ${package.ServiceImpl}.${table.serviceImplName}; import org.springframework.stereotype.Service; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; / * @Package: ${cfg.extPackagePre}.${cfg.service}.${cfg.serviceImpl} * @Description: <$!{table.comment}扩展服务实现类> * @Author: ${author} * @CreateDate: ${date} * @UpdateUser: ${author} * @UpdateDate: ${date} * @UpdateRemark: <> * @Version: 1.0 */ @Service #if(${kotlin}) open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} { } #else @ConditionalOnProperty(prefix = "spring.config-service", name = "enable", havingValue = "true") public class ${table.serviceName}${cfg.serviceImplNameFix} extends ${table.serviceImplName} implements ${table.serviceName}${cfg.classNameExt} { } #end

 controller.java.vm

package ${cfg.controllerPackage}; import ${package.Entity}.${entity}; import ${package.Service}.${table.serviceName}; import ${package.Entity}.bo.QueryBO; import ${cfg.extPackagePre}.${cfg.service}.${table.serviceName}${cfg.classNameExt}; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import java.util.List; / * @Package: ${cfg.controllerPackage} * @Description: <$!{table.comment}前端控制器> * @Author: ${author} * @CreateDate: ${date} * @UpdateUser: ${author} * @UpdateDate: ${date} * @UpdateRemark: <> * @Version: 1.0 */ #set($path=${table.name}) #set($path=$path.concat("path")) @RestController @Api(tags = "$!{table.comment}-相关接口") @RequestMapping(value = "${cfg.get($path)}", produces = MediaType.APPLICATION_JSON_VALUE) public class ${table.controllerName} { @Autowired private ${table.serviceName} i${table.serviceName}; @Autowired private ${table.serviceName}${cfg.classNameExt} i${table.serviceName}${cfg.classNameExt}; @GetMapping("list") @ApiOperation(value = "$!{table.comment}分页查询") public Page<${entity}> list${table.serviceName}ByPage(QueryBO<${entity}> query) { return i${table.serviceName}${cfg.classNameExt}.page(query.getPage() == null ? new Page() : query.getPage(), query.initQueryWrapper()); } @GetMapping("{id}") @ApiOperation(value = "$!{table.comment}获取某一实体") public ${entity} get${table.serviceName}Details(@PathVariable Long id) { return i${table.serviceName}${cfg.classNameExt}.getById(id); } @PostMapping @ApiOperation(value = "$!{table.comment}新增数据") public boolean save${table.serviceName}(@RequestBody ${entity} dto) { return i${table.serviceName}${cfg.classNameExt}.save(dto); } @PutMapping("{id}") @ApiOperation(value = "$!{table.comment}修改数据") public boolean modify${table.serviceName}(@RequestBody ${entity} dto, @PathVariable Long id) { dto.setId(id); return i${table.serviceName}${cfg.classNameExt}.updateById(dto); } @DeleteMapping("batch") @ApiOperation(value = "$!{table.comment}批量删除数据") public boolean batchRemove${table.serviceName}(@RequestParam(value = "ids") List 
  
    ids) { return i${table.serviceName}${cfg.classNameExt}.removeByIds(ids); } @DeleteMapping("{id}") @ApiOperation(value = "$!{table.comment}删除数据") public boolean remove${table.serviceName}(@PathVariable Long id) { return i${table.serviceName}${cfg.classNameExt}.removeById(id); } } 
  

★重点: 自定义输出路径

/ * 自定义配置 * * @param isCreateExt */ private static InjectionConfig injectionConfig(boolean isCreateExt) { return new InjectionConfig() { @Override public void initMap() { // 注入配置 Map 
  
    map = new HashMap<>(16); //指定表格的名称 map.put("customerTableName", true); //需要生成扩展的时候执行 if (isCreateExt) { //扩展的表名 map.put("extPackagePre", PACKAGE_PARENT_EXT); //controller包路径 map.put("controllerPackage", PACKAGE_CONTROLLER); //service包名 map.put("service", PACKAGE_NAME_SERVICE); //实现类包名 map.put("serviceImpl", PACKAGE_NAME_IMPL); //mapper包名 map.put("mapper", PACKAGE_NAME_MAPPER); //实现后缀 map.put("serviceImplNameFix", EXT_SERVICE_CLASSNAME_IMPL); //类名扩展后缀 map.put("classNameExt", EXT_ClASS_NAME); } for (String tableName : TABLES) { //指定每个类的serialVersionUID long serialVersionUID = UUID.nameUUIDFromBytes(tableName.getBytes()).getLeastSignificantBits(); map.put(tableName, Math.abs(serialVersionUID)); //计算controller的路径 StringBuilder sb = new StringBuilder(); if (StringUtils.contains(tableName, UNDERSCORE)) { sb.append(SLASH + tableName.substring(0, tableName.indexOf(UNDERSCORE))); String url = tableName.substring(tableName.indexOf(UNDERSCORE) + 1); sb.append(SLASH + CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, url)); map.put(tableName + "path", sb.toString()); continue; } sb.append(SLASH + CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, url)); map.put(tableName + "path", sb.toString()); } this.setMap(map); } } // 判断是否创建文件 .setFileCreate((configBuilder, fileType, filePath) -> { // 检查文件目录,不存在自动递归创建 File file = new File(filePath); boolean exist = file.exists(); if (!exist) { file.getParentFile().mkdirs(); } return true; }) // 自定义输出文件 .setFileOutConfigList(fileOutConfigList(isCreateExt)); } / * 自定义输出路径 * * @param isCreateExt * @return */ private static List 
   
     fileOutConfigList(boolean isCreateExt) { List 
    
      list = new ArrayList<>(); // 当前项目路径 String projectPath = System.getProperty("user.dir"); // 实体类文件输出 list.add(new FileOutConfig(ENTITY_TEMPLATE) { @Override public String outputFile(TableInfo tableInfo) { return projectPath + ENTITY_OUTPUT_PATH + tableInfo.getEntityName() + StringPool.DOT_JAVA; } }); // mapper xml文件输出 list.add(new FileOutConfig(XML_TEMPLATE) { @Override public String outputFile(TableInfo tableInfo) { return projectPath + XML_OUTPUT_PATH + tableInfo.getMapperName() + StringPool.DOT_XML; } }); // mapper文件输出 list.add(new FileOutConfig(MAPPER_TEMPLATE) { @Override public String outputFile(TableInfo tableInfo) { return projectPath + MAPPER_OUTPUT_PATH + tableInfo.getMapperName() + StringPool.DOT_JAVA; } }); // service文件输出 list.add(new FileOutConfig(SERVICE_TEMPLATE) { @Override public String outputFile(TableInfo tableInfo) { return projectPath + SERVICE_OUTPUT_PATH + tableInfo.getServiceName() + StringPool.DOT_JAVA; } }); // service impl文件输出 list.add(new FileOutConfig(SERVICE_IMPL_TEMPLATE) { @Override public String outputFile(TableInfo tableInfo) { return projectPath + SERVICE_IMPL_OUTPUT_PATH + tableInfo.getServiceImplName() + StringPool.DOT_JAVA; } }); //----------------------------------------------是否需要生成扩展------------------------------------------------------ if (isCreateExt) { // mapperExt xml文件输出 list.add(new FileOutConfig(XML_TEMPLATE_EXT) { @Override public String outputFile(TableInfo tableInfo) { return projectPath + XML_OUTPUT_PATH_EXT + tableInfo.getMapperName() + EXT_ClASS_NAME + StringPool.DOT_XML; } }); // mapperExt文件输出 list.add(new FileOutConfig(MAPPER_TEMPLATE_EXT) { @Override public String outputFile(TableInfo tableInfo) { return projectPath + MAPPER_OUTPUT_PATH_EXT + tableInfo.getMapperName() + EXT_ClASS_NAME + StringPool.DOT_JAVA; } }); // serviceExt文件输出 list.add(new FileOutConfig(SERVICE_TEMPLATE_EXT) { @Override public String outputFile(TableInfo tableInfo) { return projectPath + SERVICE_OUTPUT_PATH_EXT + tableInfo.getServiceName() + EXT_ClASS_NAME + StringPool.DOT_JAVA; } }); // serviceExt impl文件输出 list.add(new FileOutConfig(SERVICE_IMPL_TEMPLATE_EXT) { @Override public String outputFile(TableInfo tableInfo) { return projectPath + SERVICE_IMPL_OUTPUT_PATH_EXT + tableInfo.getServiceName() + EXT_SERVICE_CLASSNAME_IMPL + StringPool.DOT_JAVA; } }); //---------------------------------------------------------------------------------------------------- } // controller文件输出 list.add(new FileOutConfig(CONTROLLER_TEMPLATE) { @Override public String outputFile(TableInfo tableInfo) { return projectPath + CONTROLLER_OUTPUT_PATH + tableInfo.getControllerName() + StringPool.DOT_JAVA; } }); return list; } 
     
    
  

 执行生成程序

 public static void main(String[] args) { boolean isCreateExt = true; builder(isCreateExt); } / * 执行自动代码生成程序 * * @param isCreateExt */ private static void builder(boolean isCreateExt) { new AutoGenerator().setGlobalConfig(globalConfig()) .setDataSource(dataSourceConfig()) .setStrategy(strategyConfig()) .setCfg(injectionConfig(isCreateExt)) .setPackageInfo( new PackageConfig() .setParent(PACKAGE_PARENT) ) .execute(); }

 生成的效果如下

 最详细的mybatis plus代码生成配置--自定义生成代码路径并生成扩展类--高级配置

总结

1.通过自定义模版,生成不同的文件到不同的项目中,使得实体等文件可以被重复利用

2.生成扩展的ext文件,下次再生成的时候,可以不覆盖ext文件,表结构改动之后基础文件可快速生成并覆盖旧文件

3.因为是根据表名生成序列号,不会存在反序列化的问题

4.自定义业务实现和多表复杂业务都可放在ext扩展类中

5.springboot可采用@ConditionalOnProperty注解启用某些特定的service

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/176501.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午9:46
下一篇 2026年3月26日 下午9:47


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号