一、本文内容
- 上文出入参、converter、controller自动生成后,都进行了手动调整,本文将这些手动调整的内容,整合为自动生成代码
- 解决swagger刷新报错问题
二、解决swagger刷新报错问题
添加依赖,指定swagger-models版本为1.5.22,默认为1.5.20
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.22</version>
</dependency>
三、修改MybatisPlusGenerator配置
- 添加
@FixMethodOrder(MethodSorters.NAME_ASCENDING)控制测试方法执行顺序 StrategyConfig初始化改为私有方法,在setUp方法调用,保证每个测试用例执行前重新初始化一遍,避免测试用例赋值的相互影响- 标准生成方法禁用
controller,单独写用例实现个性化定义 - 自定义
SaveCommand生成模板,指定包名model.command,指定模板templates/entitySaveCommand.java,指定类名entityName + "SaveCommand",忽略字段"id", "version", "delete_flag", "create_time", "update_time", "updated_by" - 自定义
UpdateCommand生成模板,控制bigint生成String类型,指定包名model.command,指定模板templates/entityUpdateCommand.java,指定类名entityName + "UpdateCommand",忽略字段"delete_flag", "create_time", "created_by", "update_time" - 自定义
DetailResp生成模板,控制bigint生成String类型,指定包名model.resp,指定模板templates/entityDetailResp.java,指定类名entityName + "DetailResp",忽略字段"delete_flag",情况version乐观锁版本设置 - 自定义
PageResp生成模板,控制bigint生成String类型,指定包名model.resp,指定模板templates/entityPageResp.java,指定类名entityName + "PageResp",忽略字段"delete_flag",情况version乐观锁版本设置 - 自定义
Converter生成模板,指定包名model.converter,指定模板templates/converter.java,指定类名entityName + "Converter",复用Controller的生成方法 - 自定义
Controller生成模板,指定包名controller,指定模板templates/controller.java,指定类名entityName + "Converter",这里仅生成controller类
package com.example.demo.config;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
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.TemplateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import java.sql.Types;
import java.util.*;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class MybatisPlusGenerator {
private static final String DB_URL = "jdbc:mysql://localhost:3306/demo?useSSL=false";
private static final String DB_USERNAME = "root";
private static final String DB_PASSWORD = "123456";
private static final List<String> TABLES = Arrays.asList(
//"user_info",
"system_log"
);
private static final String AUTHOR = "chenzl";
private static final String PKG_PARENT = "com.example.demo";
private static final String PKG_ENTITY = "model";
private static final String PKG_MAPPER = "dao";
/**
* 数据源配置
*/
private static final DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig.Builder(DB_URL, DB_USERNAME, DB_PASSWORD)
//数据库 schema(部分数据库适用) mybatis-plus
//.schema("demo")
.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
})
.build();
private static final GlobalConfig GLOBAL_CONFIG = new GlobalConfig.Builder()
//禁止打开输出目录 默认值:true
.disableOpenDir()
//指定输出目录
.outputDir(System.getProperty("user.dir") + "/src/main/java")
//设置作者
.author(AUTHOR)
//开启swagger模式
.enableSwagger()
//时间策略 DateType.ONLY_DATE 默认值: DateType.TIME_PACK
//.dateType(DateType.TIME_PACK)
//注释日期 默认值: yyyy-MM-dd
//.commentDate("yyyy-MM-dd HH:mm:ss")
.build();
private static final PackageConfig PACKAGE_CONFIG = new PackageConfig.Builder()
//设置父包名
.parent(PKG_PARENT)
//父包模块名 默认值:无
//.moduleName("demo")
.entity(PKG_ENTITY)
//Mapper包名 默认值:mapper
.mapper(PKG_MAPPER)
//设置mapperXml生成路径
.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/src/main/resources/mapper"))
.build();
private StrategyConfig strategyConfig;
private void initStrategyConfig() {
strategyConfig = new StrategyConfig.Builder()
// 设置需要生成的表名
.addInclude(TABLES)
// 设置过滤表前缀
//.addTablePrefix("t_")
//controller配置
.controllerBuilder()
//覆盖已生成文件
.enableFileOverride()
//开启生成@RestController 控制器 默认值:false
.enableRestStyle()
//service配置
.serviceBuilder()
//覆盖已生成文件
.enableFileOverride()
.convertServiceFileName((entityName) -> entityName + "Service")
.convertServiceImplFileName((entityName) -> entityName + "ServiceImpl")
//mapper配置
.mapperBuilder()
//覆盖已生成文件
.enableFileOverride()
//启用 BaseResultMap 生成 默认值:false
.enableBaseResultMap()
//启用 BaseColumnList 默认值:false
.enableBaseColumnList()
//转换 mapper 类文件名称 默认值:%sMapper
//.convertMapperFileName((entityName) -> entityName + "Mapper")
//转换 xml 文件名称 默认值:%sMapper
//.convertXmlFileName((entityName) -> entityName + "Mapper")
//entity配置
.entityBuilder()
//覆盖已生成文件
.enableFileOverride()
//禁用生成 serialVersionUID 默认值:true
.disableSerialVersionUID()
//开启lombok模型 默认值:false
.enableLombok()
//开启Boolean类型字段移除is前缀 默认值:false mysql 数据库字段类型为tinyint(1)时,会自动转换为Boolean类型
.enableRemoveIsPrefix()
//乐观锁字段名(数据库字段) versionColumnName与versionPropertyName二选一即可
.versionColumnName("version")
//逻辑删除字段名(数据库字段) logicDeleteColumnName与logicDeletePropertyName二选一即可
.logicDeleteColumnName("delete_flag")
//转换文件名称
//.convertFileName((entityName) -> entityName + "PO")
//格式化文件名称
//.formatFileName("%sPO")
//全局主键类型
.idType(IdType.ASSIGN_ID)
.addTableFills(Arrays.asList(
new Column("create_time", FieldFill.INSERT),
new Column("created_by", FieldFill.INSERT),
new Column("update_time", FieldFill.INSERT_UPDATE),
new Column("updated_by", FieldFill.INSERT_UPDATE)
))
.build();
}
@Before
public void setUp() {
initStrategyConfig();
}
@Test
public void execute01() {
AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
generator.global(GLOBAL_CONFIG);
generator.packageInfo(PACKAGE_CONFIG);
generator.template(new TemplateConfig.Builder()
.disable(TemplateType.CONTROLLER)
.build());
generator.strategy(strategyConfig);
// 使用Freemarker引擎模板,默认的是Velocity引擎模板
generator.execute(new FreemarkerTemplateEngine());
}
@Test
public void execute02_SaveCommand() {
AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
generator.global(GLOBAL_CONFIG);
generator.packageInfo(new PackageConfig.Builder()
//设置父包名
.parent(PKG_PARENT)
//父包模块名 默认值:无
.entity("model.command")
.build());
generator.template(new TemplateConfig.Builder()
.disable()
.entity("templates/entitySaveCommand.java")
.build());
strategyConfig.entity().getTableFillList().clear();
generator.strategy(strategyConfig.entityBuilder()
.convertFileName((entityName) -> entityName + "SaveCommand")
.addIgnoreColumns("id", "version", "delete_flag", "create_time", "update_time", "updated_by")
.build());
generator.execute(new FreemarkerTemplateEngine());
}
@Test
public void execute03_UpdateCommand() {
DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig.Builder(DB_URL, DB_USERNAME, DB_PASSWORD)
.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
if (typeCode == Types.BIGINT) {
// 自定义类型转换
return DbColumnType.STRING;
}
return typeRegistry.getColumnType(metaInfo);
})
.build();
AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
generator.global(GLOBAL_CONFIG);
generator.packageInfo(new PackageConfig.Builder()
//设置父包名
.parent(PKG_PARENT)
//父包模块名 默认值:无
.entity("model.command")
.build());
generator.template(new TemplateConfig.Builder()
.disable()
.entity("templates/entityUpdateCommand.java")
.build());
strategyConfig.entity().getTableFillList().clear();
generator.strategy(strategyConfig.entityBuilder()
.convertFileName((entityName) -> entityName + "UpdateCommand")
.addIgnoreColumns("delete_flag", "create_time", "created_by", "update_time")
//清空标准设置中的version字段
.versionColumnName("")
.idType(null)
.build());
generator.execute(new FreemarkerTemplateEngine());
}
@Test
public void execute04_DetailResp() {
DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig.Builder(DB_URL, DB_USERNAME, DB_PASSWORD)
.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
if (typeCode == Types.BIGINT) {
// 自定义类型转换
return DbColumnType.STRING;
}
return typeRegistry.getColumnType(metaInfo);
})
.build();
AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
generator.global(GLOBAL_CONFIG);
generator.packageInfo(new PackageConfig.Builder()
//设置父包名
.parent(PKG_PARENT)
//父包模块名 默认值:无
.entity("model.resp")
.build());
generator.template(new TemplateConfig.Builder()
.disable()
.entity("templates/entityDetailResp.java")
.build());
strategyConfig.entity().getTableFillList().clear();
generator.strategy(strategyConfig.entityBuilder()
.convertFileName((entityName) -> entityName + "DetailResp")
.addIgnoreColumns("delete_flag")
//清空标准设置中的version字段
.versionColumnName("")
.idType(null)
.build());
generator.execute(new FreemarkerTemplateEngine());
}
@Test
public void execute05_PageResp() {
DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig.Builder(DB_URL, DB_USERNAME, DB_PASSWORD)
.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
if (typeCode == Types.BIGINT) {
// 自定义类型转换
return DbColumnType.STRING;
}
return typeRegistry.getColumnType(metaInfo);
})
.build();
AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
generator.global(GLOBAL_CONFIG);
generator.packageInfo(new PackageConfig.Builder()
//设置父包名
.parent(PKG_PARENT)
//父包模块名 默认值:无
.entity("model.resp")
.build());
generator.template(new TemplateConfig.Builder()
.disable()
.entity("templates/entityPageResp.java")
.build());
strategyConfig.entity().getTableFillList().clear();
generator.strategy(strategyConfig.entityBuilder()
.convertFileName((entityName) -> entityName + "PageResp")
.addIgnoreColumns("delete_flag")
//清空标准设置中的version字段
.versionColumnName("")
.idType(null)
.build());
generator.execute(new FreemarkerTemplateEngine());
}
@Test
public void execute06_converter() {
AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
generator.global(GLOBAL_CONFIG);
generator.packageInfo(new PackageConfig.Builder()
//设置父包名
.parent(PKG_PARENT)
.entity(PKG_ENTITY)
//父包模块名 默认值:无
.controller("model.converter")
.build());
generator.template(new TemplateConfig.Builder()
.disable()
.controller("templates/converter.java")
.build());
generator.strategy(strategyConfig.controllerBuilder()
.convertFileName((entityName) -> entityName + "Converter")
.build());
generator.execute(new FreemarkerTemplateEngine());
}
@Test
public void execute07_controller() {
AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
generator.global(GLOBAL_CONFIG);
generator.packageInfo(new PackageConfig.Builder()
//设置父包名
.parent(PKG_PARENT)
.entity(PKG_ENTITY)
.build());
generator.template(new TemplateConfig.Builder()
.disable()
.controller("templates/controller.java")
.build());
generator.strategy(strategyConfig.controllerBuilder()
.build());
generator.execute(new FreemarkerTemplateEngine());
}
}
四、自定义freemarker模板
1.entitySaveCommand.java.ftl
package ${package.Entity};
<#if springdoc>
import io.swagger.v3.oas.annotations.media.Schema;
<#elseif swagger>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
<#if chainModel>
import lombok.experimental.Accessors;
</#if>
</#if>
/**
* <p>
* ${table.comment!}新增入参
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
<#if chainModel>
@Accessors(chain = true)
</#if>
</#if>
<#if springdoc>
@Schema(name = "${entity}", description = "${table.comment!}")
<#elseif swagger>
@ApiModel(value = "${entity}", description = "${table.comment!}新增入参")
</#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#elseif entitySerialVersionUID>
public class ${entity} implements Serializable {
<#else>
public class ${entity} {
</#if>
<#if entitySerialVersionUID>
private static final long serialVersionUID = 1L;
</#if>
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}"/>
</#if>
<#if field.comment!?length gt 0>
<#if springdoc>
@Schema(description = "${field.comment}")
<#elseif swagger>
@ApiModelProperty("${field.comment}")
<#else>
/**
* ${field.comment}
*/
</#if>
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokModel>
<#list table.fields as field>
<#if field.propertyType == "boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
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}) {
</#if>
this.${field.propertyName} = ${field.propertyName};
<#if chainModel>
return this;
</#if>
}
</#list>
</#if>
<#if entityColumnConstant>
<#list table.fields as field>
public static final String ${field.name?upper_case} = "${field.name}";
</#list>
</#if>
<#if activeRecord>
@Override
public Serializable pkVal() {
<#if keyPropertyName??>
return this.${keyPropertyName};
<#else>
return null;
</#if>
}
</#if>
<#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} +
</#if>
</#list>
"}";
}
</#if>
}
2.entityUpdateCommand.java.ftl
package ${package.Entity};
<#if springdoc>
import io.swagger.v3.oas.annotations.media.Schema;
<#elseif swagger>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
<#if chainModel>
import lombok.experimental.Accessors;
</#if>
</#if>
import javax.validation.constraints.NotBlank;
/**
* <p>
* ${table.comment!}修改入参
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
<#if chainModel>
@Accessors(chain = true)
</#if>
</#if>
<#if springdoc>
@Schema(name = "${entity}", description = "${table.comment!}")
<#elseif swagger>
@ApiModel(value = "${entity}", description = "${table.comment!}修改入参")
</#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#elseif entitySerialVersionUID>
public class ${entity} implements Serializable {
<#else>
public class ${entity} {
</#if>
<#if entitySerialVersionUID>
private static final long serialVersionUID = 1L;
</#if>
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}"/>
</#if>
<#if field.comment!?length gt 0>
<#if springdoc>
@Schema(description = "${field.comment}")
<#elseif swagger>
@ApiModelProperty("${field.comment}")
<#else>
/**
* ${field.comment}
*/
</#if>
</#if>
<#if field.propertyName == "id">
@NotBlank(message = "id不能为空")
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokModel>
<#list table.fields as field>
<#if field.propertyType == "boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
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}) {
</#if>
this.${field.propertyName} = ${field.propertyName};
<#if chainModel>
return this;
</#if>
}
</#list>
</#if>
<#if entityColumnConstant>
<#list table.fields as field>
public static final String ${field.name?upper_case} = "${field.name}";
</#list>
</#if>
<#if activeRecord>
@Override
public Serializable pkVal() {
<#if keyPropertyName??>
return this.${keyPropertyName};
<#else>
return null;
</#if>
}
</#if>
<#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} +
</#if>
</#list>
"}";
}
</#if>
}
3.entityDetailResp.java.ftl
package ${package.Entity};
<#if springdoc>
import io.swagger.v3.oas.annotations.media.Schema;
<#elseif swagger>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
<#if chainModel>
import lombok.experimental.Accessors;
</#if>
</#if>
import java.time.LocalDateTime;
/**
* <p>
* ${table.comment!}详情反参
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
<#if chainModel>
@Accessors(chain = true)
</#if>
</#if>
<#if springdoc>
@Schema(name = "${entity}", description = "${table.comment!}")
<#elseif swagger>
@ApiModel(value = "${entity}", description = "${table.comment!}详情反参")
</#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#elseif entitySerialVersionUID>
public class ${entity} implements Serializable {
<#else>
public class ${entity} {
</#if>
<#if entitySerialVersionUID>
private static final long serialVersionUID = 1L;
</#if>
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}"/>
</#if>
<#if field.comment!?length gt 0>
<#if springdoc>
@Schema(description = "${field.comment}")
<#elseif swagger>
@ApiModelProperty("${field.comment}")
<#else>
/**
* ${field.comment}
*/
</#if>
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokModel>
<#list table.fields as field>
<#if field.propertyType == "boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
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}) {
</#if>
this.${field.propertyName} = ${field.propertyName};
<#if chainModel>
return this;
</#if>
}
</#list>
</#if>
<#if entityColumnConstant>
<#list table.fields as field>
public static final String ${field.name?upper_case} = "${field.name}";
</#list>
</#if>
<#if activeRecord>
@Override
public Serializable pkVal() {
<#if keyPropertyName??>
return this.${keyPropertyName};
<#else>
return null;
</#if>
}
</#if>
<#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} +
</#if>
</#list>
"}";
}
</#if>
}
4.entityPageResp.java.ftl
package ${package.Entity};
<#if springdoc>
import io.swagger.v3.oas.annotations.media.Schema;
<#elseif swagger>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
<#if chainModel>
import lombok.experimental.Accessors;
</#if>
</#if>
import java.time.LocalDateTime;
/**
* <p>
* ${table.comment!}分页反参
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
<#if chainModel>
@Accessors(chain = true)
</#if>
</#if>
<#if springdoc>
@Schema(name = "${entity}", description = "${table.comment!}")
<#elseif swagger>
@ApiModel(value = "${entity}", description = "${table.comment!}分页反参")
</#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#elseif entitySerialVersionUID>
public class ${entity} implements Serializable {
<#else>
public class ${entity} {
</#if>
<#if entitySerialVersionUID>
private static final long serialVersionUID = 1L;
</#if>
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}"/>
</#if>
<#if field.comment!?length gt 0>
<#if springdoc>
@Schema(description = "${field.comment}")
<#elseif swagger>
@ApiModelProperty("${field.comment}")
<#else>
/**
* ${field.comment}
*/
</#if>
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokModel>
<#list table.fields as field>
<#if field.propertyType == "boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
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}) {
</#if>
this.${field.propertyName} = ${field.propertyName};
<#if chainModel>
return this;
</#if>
}
</#list>
</#if>
<#if entityColumnConstant>
<#list table.fields as field>
public static final String ${field.name?upper_case} = "${field.name}";
</#list>
</#if>
<#if activeRecord>
@Override
public Serializable pkVal() {
<#if keyPropertyName??>
return this.${keyPropertyName};
<#else>
return null;
</#if>
}
</#if>
<#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} +
</#if>
</#list>
"}";
}
</#if>
}
5.converter.java.ftl
package ${package.Controller};
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ${package.Entity}.${entity};
import ${package.Entity}.command.${entity}SaveCommand;
import ${package.Entity}.command.${entity}UpdateCommand;
import ${package.Entity}.resp.${entity}DetailResp;
import ${package.Entity}.resp.${entity}PageResp;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* <p>
* ${table.comment!} 转换器
* </p>
*
* @author ${author}
* @since ${date}
*/
@Mapper
public interface ${entity}Converter {
${entity}Converter INSTANCE = Mappers.getMapper(${entity}Converter.class);
${entity} convert(${entity}SaveCommand source);
${entity} convert(${entity}UpdateCommand source);
${entity}DetailResp convert2DetailResp(${entity} source);
Page<${entity}PageResp> convert2PageResp(Page<${entity}> source);
}
6.修改controller.java.ftl
package ${package.Controller};
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.http.BusinessException;
import com.example.demo.common.http.RestResult;
import ${package.Entity}.${entity};
import ${package.Entity}.command.${entity}SaveCommand;
import ${package.Entity}.command.${entity}UpdateCommand;
import ${package.Entity}.converter.${entity}Converter;
import ${package.Entity}.resp.${entity}DetailResp;
import ${package.Entity}.resp.${entity}PageResp;
import ${package.Service}.${table.serviceName};
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;
</#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
import javax.annotation.Resource;
/**
* <p>
* ${table.comment!} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if restControllerStyle>
@RestController
<#else>
@Controller
</#if>
@RequestMapping("<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
<#if kotlin>
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if>
<#else>
@Api(tags = "${table.comment!}")
<#if superControllerClass??>
public class ${table.controllerName} extends ${superControllerClass} {
<#else>
public class ${table.controllerName} {
</#if>
@Resource
private ${table.serviceName} ${table.serviceName?uncap_first};
@PostMapping("/save")
@ApiOperation(value = "新增${table.comment!}")
public RestResult<String> save(@RequestBody @Validated ${entity}SaveCommand command) {
${entity} ${entity?uncap_first} = ${entity}Converter.INSTANCE.convert(command);
${table.serviceName?uncap_first}.save(${entity?uncap_first});
return RestResult.getSuccessResult(String.valueOf(${entity?uncap_first}.getId()));
}
@PostMapping("/removeById")
@ApiOperation(value = "根据id删除${table.comment!}")
@ApiImplicitParams(
@ApiImplicitParam(name = "id", value = "主键id", required = true, dataType = "String")
)
public RestResult<Boolean> removeById(String id) {
boolean success = ${table.serviceName?uncap_first}.removeById(Long.parseLong(id));
return RestResult.getSuccessResult(success);
}
@PostMapping("/updateById")
@ApiOperation(value = "根据id更新${table.comment!}")
public RestResult<Boolean> updateById(@RequestBody @Validated ${entity}UpdateCommand command) {
${entity} ${entity?uncap_first} = ${entity}Converter.INSTANCE.convert(command);
boolean success = ${table.serviceName?uncap_first}.updateById(${entity?uncap_first});
return RestResult.getSuccessResult(success);
}
@PostMapping("/getById")
@ApiOperation(value = "根据id查询${table.comment!}")
@ApiImplicitParams(
@ApiImplicitParam(name = "id", value = "主键id", required = true, dataType = "String")
)
public RestResult<${entity}DetailResp> getById(String id) {
${entity} ${entity?uncap_first} = ${table.serviceName?uncap_first}.getById(Long.parseLong(id));
if (null == ${entity?uncap_first}) {
throw new BusinessException("id不存在");
}
${entity}DetailResp resp = ${entity}Converter.INSTANCE.convert2DetailResp(${entity?uncap_first});
return RestResult.getSuccessResult(resp);
}
@PostMapping("/page")
@ApiOperation(value = "分页查询${table.comment!}")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "当前页码", dataType = "Integer", paramType = "query"),
@ApiImplicitParam(name = "pageSize", value = "每页显示条数", dataType = "Integer", paramType = "query")
})
public RestResult<Page<${entity}PageResp>> page(Integer pageNum, Integer pageSize) {
Page<${entity}> page = ${table.serviceName?uncap_first}.page(new Page<>(pageNum, pageSize));
Page<${entity}PageResp> resp = ${entity}Converter.INSTANCE.convert2PageResp(page);
return RestResult.getSuccessResult(resp);
}
}
</#if>
五、功能验证
- 执行
MybatisPlusGenerator类,可以看到用例均执行成功,重新生成了出入参、controller、service、mapper - 表设置新增user_info,可以生成userInfo相关内容
最新建表SQL
CREATE TABLE `system_log` (
`id` bigint(20) NOT NULL COMMENT '主键id',
`description` varchar(50) DEFAULT NULL COMMENT '日志信息描述',
`method` varchar(20) DEFAULT NULL COMMENT '方法名称',
`log_type` varchar(10) DEFAULT NULL COMMENT '日志类型 0是正常,1是异常',
`request_ip` varchar(30) DEFAULT NULL COMMENT '请求的ip',
`exception_code` varchar(50) DEFAULT NULL COMMENT '异常错误码',
`exception_detail` varchar(255) DEFAULT NULL COMMENT '异常详情',
`params` varchar(1000) DEFAULT NULL COMMENT '请求参数',
`user_id` varchar(32) DEFAULT NULL COMMENT '请求的用户id',
`delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否删除:0-否,1-是',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`created_by` varchar(128) DEFAULT '' COMMENT '创建人',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '最后修改时间',
`updated_by` varchar(128) DEFAULT '' COMMENT '最后修改人',
`version` int(8) DEFAULT '0' COMMENT '版本号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统日志表';
CREATE TABLE `user_info` (
`id` bigint(20) NOT NULL COMMENT '主键id',
`user_name` varchar(100) DEFAULT NULL COMMENT '用户名',
`password` varchar(100) DEFAULT NULL COMMENT '用户密码',
`avatar` varchar(100) DEFAULT NULL COMMENT '图像',
`is_vip` tinyint(1) DEFAULT '0' COMMENT '是否VIP',
`delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否删除:0-否,1-是',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`created_by` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '' COMMENT '创建人',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '最后修改时间',
`updated_by` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '' COMMENT '最后修改人',
`version` int(8) DEFAULT '0' COMMENT '版本号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户表';
六、项目地址
PS:可以通过tag下载本文对应的代码版本
七、结尾
自定义freemarker模板已完成,有问题可以联系chenzhenlindx@qq.com