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(); }
生成的效果如下

总结
1.通过自定义模版,生成不同的文件到不同的项目中,使得实体等文件可以被重复利用
2.生成扩展的ext文件,下次再生成的时候,可以不覆盖ext文件,表结构改动之后基础文件可快速生成并覆盖旧文件
3.因为是根据表名生成序列号,不会存在反序列化的问题
4.自定义业务实现和多表复杂业务都可放在ext扩展类中
5.springboot可采用@ConditionalOnProperty注解启用某些特定的service
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/176501.html原文链接:https://javaforall.net
