代码生成器:简化 vo 和 convert 的生成逻辑

This commit is contained in:
zhijiantianya@gmail.com 2023-11-15 21:03:16 +08:00
parent 7e6b084f77
commit 91d7938ddf
16 changed files with 159 additions and 250 deletions
yudao-module-infra/yudao-module-infra-biz/src/main

View File

@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.infra.service.codegen.inner; package cn.iocoder.yudao.module.infra.service.codegen.inner;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
@ -15,6 +14,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
@ -63,16 +63,11 @@ public class CodegenEngine {
*/ */
private static final Map<String, String> SERVER_TEMPLATES = MapUtil.<String, String>builder(new LinkedHashMap<>()) // 有序 private static final Map<String, String> SERVER_TEMPLATES = MapUtil.<String, String>builder(new LinkedHashMap<>()) // 有序
// Java module-biz Main // Java module-biz Main
.put(javaTemplatePath("controller/vo/baseVO"), javaModuleImplVOFilePath("BaseVO"))
.put(javaTemplatePath("controller/vo/createReqVO"), javaModuleImplVOFilePath("CreateReqVO"))
.put(javaTemplatePath("controller/vo/pageReqVO"), javaModuleImplVOFilePath("PageReqVO")) .put(javaTemplatePath("controller/vo/pageReqVO"), javaModuleImplVOFilePath("PageReqVO"))
.put(javaTemplatePath("controller/vo/respVO"), javaModuleImplVOFilePath("RespVO"))
.put(javaTemplatePath("controller/vo/updateReqVO"), javaModuleImplVOFilePath("UpdateReqVO"))
.put(javaTemplatePath("controller/vo/listReqVO"), javaModuleImplVOFilePath("ListReqVO")) .put(javaTemplatePath("controller/vo/listReqVO"), javaModuleImplVOFilePath("ListReqVO"))
.put(javaTemplatePath("controller/vo/excelVO"), javaModuleImplVOFilePath("ExcelVO")) .put(javaTemplatePath("controller/vo/respVO"), javaModuleImplVOFilePath("RespVO"))
.put(javaTemplatePath("controller/vo/saveReqVO"), javaModuleImplVOFilePath("SaveReqVO"))
.put(javaTemplatePath("controller/controller"), javaModuleImplControllerFilePath()) .put(javaTemplatePath("controller/controller"), javaModuleImplControllerFilePath())
.put(javaTemplatePath("convert/convert"),
javaModuleImplMainFilePath("convert/${table.businessName}/${table.className}Convert"))
.put(javaTemplatePath("dal/do"), .put(javaTemplatePath("dal/do"),
javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${table.className}DO")) javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${table.className}DO"))
.put(javaTemplatePath("dal/do_sub"), // 特殊主子表专属逻辑 .put(javaTemplatePath("dal/do_sub"), // 特殊主子表专属逻辑
@ -192,6 +187,7 @@ public class CodegenEngine {
globalBindingMap.put("DictConvertClassName", DictConvert.class.getName()); globalBindingMap.put("DictConvertClassName", DictConvert.class.getName());
globalBindingMap.put("OperateLogClassName", OperateLog.class.getName()); globalBindingMap.put("OperateLogClassName", OperateLog.class.getName());
globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName()); globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName());
globalBindingMap.put("BeanUtils", BeanUtils.class.getName());
} }
/** /**
@ -218,11 +214,16 @@ public class CodegenEngine {
generateSubCode(table, subTables, result, vmPath, filePath, bindingMap); generateSubCode(table, subTables, result, vmPath, filePath, bindingMap);
return; return;
// 2.2 特殊树表专属逻辑 // 2.2 特殊树表专属逻辑
} else if (isPageTemplate(vmPath)) { } else if (isPageReqVOTemplate(vmPath)) {
// 减少多余的类生成例如说 PageVO.java // 减少多余的类生成例如说 PageVO.java
if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) {
return; return;
} }
} else if (isListReqVOTemplate(vmPath)) {
// 减少多余的类生成例如说 ListVO.java
if (!CodegenTemplateTypeEnum.isTree(table.getTemplateType())) {
return;
}
} }
// 2.3 默认生成 // 2.3 默认生成
generateCode(result, vmPath, filePath, bindingMap); generateCode(result, vmPath, filePath, bindingMap);
@ -469,8 +470,12 @@ public class CodegenEngine {
return path.contains("_sub"); return path.contains("_sub");
} }
private static boolean isPageTemplate(String path) { private static boolean isPageReqVOTemplate(String path) {
return path.contains("page"); return path.contains("pageReqVO");
}
private static boolean isListReqVOTemplate(String path) {
return path.contains("listReqVO");
} }
} }

View File

@ -18,6 +18,7 @@ import java.io.IOException;
import ${PageParamClassName}; import ${PageParamClassName};
import ${PageResultClassName}; import ${PageResultClassName};
import ${CommonResultClassName}; import ${CommonResultClassName};
import ${BeanUtils};
import static ${CommonResultClassName}.success; import static ${CommonResultClassName}.success;
import ${ExcelUtilsClassName}; import ${ExcelUtilsClassName};
@ -31,7 +32,6 @@ import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.business
#foreach ($subTable in $subTables) #foreach ($subTable in $subTables)
import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO; import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
#end #end
import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert;
import ${basePackage}.module.${table.moduleName}.service.${table.businessName}.${table.className}Service; import ${basePackage}.module.${table.moduleName}.service.${table.businessName}.${table.className}Service;
@Tag(name = "${sceneEnum.name} - ${table.classComment}") @Tag(name = "${sceneEnum.name} - ${table.classComment}")
@ -49,7 +49,7 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")
#end #end
public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) { public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO) {
return success(${classNameVar}Service.create${simpleClassName}(createReqVO)); return success(${classNameVar}Service.create${simpleClassName}(createReqVO));
} }
@ -58,7 +58,7 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")
#end #end
public CommonResult<Boolean> update${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) { public CommonResult<Boolean> update${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO) {
${classNameVar}Service.update${simpleClassName}(updateReqVO); ${classNameVar}Service.update${simpleClassName}(updateReqVO);
return success(true); return success(true);
} }
@ -82,7 +82,7 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
#end #end
public CommonResult<${sceneEnum.prefixClass}${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) { public CommonResult<${sceneEnum.prefixClass}${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) {
${table.className}DO ${classNameVar} = ${classNameVar}Service.get${simpleClassName}(id); ${table.className}DO ${classNameVar} = ${classNameVar}Service.get${simpleClassName}(id);
return success(${table.className}Convert.INSTANCE.convert(${classNameVar})); return success(BeanUtils.toBean(${classNameVar}, ${sceneEnum.prefixClass}${table.className}RespVO.class));
} }
#if ( $table.templateType != 2 ) #if ( $table.templateType != 2 )
@ -93,7 +93,7 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
#end #end
public CommonResult<PageResult<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}Page(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) { public CommonResult<PageResult<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}Page(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) {
PageResult<${table.className}DO> pageResult = ${classNameVar}Service.get${simpleClassName}Page(pageReqVO); PageResult<${table.className}DO> pageResult = ${classNameVar}Service.get${simpleClassName}Page(pageReqVO);
return success(${table.className}Convert.INSTANCE.convertPage(pageResult)); return success(BeanUtils.toBean(pageResult, ${sceneEnum.prefixClass}${table.className}RespVO.class));
} }
## 特殊:树表专属逻辑(树不需要分页接口) ## 特殊:树表专属逻辑(树不需要分页接口)
@ -105,7 +105,7 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
#end #end
public CommonResult<List<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}List(@Valid ${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO) { public CommonResult<List<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}List(@Valid ${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO) {
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(listReqVO); List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(listReqVO);
return success(${table.className}Convert.INSTANCE.convertList(list)); return success(BeanUtils.toBean(list, ${sceneEnum.prefixClass}${table.className}RespVO.class));
} }
#end #end
@ -115,13 +115,25 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')")
#end #end
@OperateLog(type = EXPORT) @OperateLog(type = EXPORT)
#if ( $table.templateType != 2 )
public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}Page(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${table.className}RespVO.class,
BeanUtils.toBean(list, ${table.className}RespVO.class));
}
## 特殊:树表专属逻辑(树不需要分页接口)
#else
public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO, public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO,
HttpServletResponse response) throws IOException { HttpServletResponse response) throws IOException {
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(listReqVO); List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(listReqVO);
// 导出 Excel // 导出 Excel
List<${sceneEnum.prefixClass}${table.className}ExcelVO> dataList = ${table.className}Convert.INSTANCE.convertList02(list); ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${table.className}RespVO.class,
ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${sceneEnum.prefixClass}${table.className}ExcelVO.class, dataList); BeanUtils.toBean(list, ${table.className}RespVO.class));
} }
#end
## 特殊:主子表专属逻辑 ## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables) #foreach ($subTable in $subTables)

View File

@ -1,13 +0,0 @@
## 提供给 baseVO、createVO、updateVO 生成字段
@Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
#if (!${column.nullable})## 判断 @NotEmpty 和 @NotNull 注解
#if (${column.javaType} == 'String')
@NotEmpty(message = "${column.columnComment}不能为空")
#else
@NotNull(message = "${column.columnComment}不能为空")
#end
#end
#if (${column.javaType} == "LocalDateTime")## 时间类型
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
#end
private ${column.javaType} ${column.javaField};

View File

@ -1,30 +0,0 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.*;
## 处理 Date 字段的引入
#foreach ($column in $columns)
#if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult})
&& ${column.javaType} == "LocalDateTime")## 时间类型
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
#break
#end
#end
@Schema(description = "${sceneEnum.name} - ${table.classComment}创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ${sceneEnum.prefixClass}${table.className}CreateReqVO extends ${sceneEnum.prefixClass}${table.className}BaseVO {
#foreach ($column in $columns)
#if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult}))##不是通用字段
#parse("codegen/java/controller/vo/_column.vm")
#end
#end
}

View File

@ -1,47 +0,0 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
#foreach ($column in $columns)
#if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#break
#end
#if (${column.javaType} == "LocalDateTime")
import java.time.LocalDateTime;
#break
#end
#end
import com.alibaba.excel.annotation.ExcelProperty;
#foreach ($column in $columns)
#if ("$!column.dictType" != "")## 有设置数据字典
import ${DictFormatClassName};
import ${DictConvertClassName};
#break
#end
#end
/**
* ${table.classComment} Excel VO
*
* @author ${table.author}
*/
@Data
public class ${sceneEnum.prefixClass}${table.className}ExcelVO {
#foreach ($column in $columns)
#if (${column.listOperationResult})##返回字段
#if ("$!column.dictType" != "")##处理枚举值
@ExcelProperty(value = "${column.columnComment}", converter = DictConvert.class)
@DictFormat("${column.dictType}") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
#else
@ExcelProperty("${column.columnComment}")
#end
private ${column.javaType} ${column.javaField};
#end
#end
}

View File

@ -4,9 +4,15 @@ import lombok.*;
import java.util.*; import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import ${PageParamClassName}; import ${PageParamClassName};
## 处理 Date 字段的引入
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperation} && ${column.javaType} == "LocalDateTime")## 时间类型 #if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#break
#end
#end
## 处理 LocalDateTime 字段的引入
#foreach ($column in $columns)
#if (${column.listOperation} && ${column.javaType} == "LocalDateTime")
import java.time.LocalDateTime; import java.time.LocalDateTime;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
@ -20,9 +26,9 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end; private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end;
#end #end
@Schema(description = "${sceneEnum.name} - ${table.classComment} Excel 导出 Request VO参数和 ${table.className}PageReqVO 是一致的") @Schema(description = "${sceneEnum.name} - ${table.classComment}列表 Request VO")
@Data @Data
public class ${sceneEnum.prefixClass}${table.className}ExportReqVO { public class ${sceneEnum.prefixClass}${table.className}ListReqVO {
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperation})##查询操作 #if (${column.listOperation})##查询操作

View File

@ -4,9 +4,15 @@ import lombok.*;
import java.util.*; import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import ${PageParamClassName}; import ${PageParamClassName};
## 处理 Date 字段的引入
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperation} && ${column.javaType} == "LocalDateTime")## 时间类型 #if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#break
#end
#end
## 处理 LocalDateTime 字段的引入
#foreach ($column in $columns)
#if (${column.listOperationCondition} && ${column.javaType} == "LocalDateTime")
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;

View File

@ -2,22 +2,51 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePac
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import java.util.*;
## 处理 BigDecimal 字段的引入
import java.util.*;
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.javaType} == "LocalDateTime") #if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#break
#end
#end
## 处理 LocalDateTime 字段的引入
#foreach ($column in $columns)
#if (${table.listOperationResult} && ${column.javaType} == "LocalDateTime")
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
#break #break
#end #end
#end #end
## 处理 Excel 导出
import com.alibaba.excel.annotation.*;
#foreach ($column in $columns)
#if ("$!column.dictType" != "")## 有设置数据字典
import ${DictFormatClassName};
import ${DictConvertClassName};
#break
#end
#end
@Schema(description = "${sceneEnum.name} - ${table.classComment} Response VO") @Schema(description = "${sceneEnum.name} - ${table.classComment} Response VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @ExcelIgnoreUnannotated
@ToString(callSuper = true) public class ${sceneEnum.prefixClass}${table.className}RespVO {
public class ${sceneEnum.prefixClass}${table.className}RespVO extends ${sceneEnum.prefixClass}${table.className}BaseVO {
## 逐个处理字段
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperationResult} && (!${column.createOperation} || !${column.updateOperation}))##不是通用字段 #if (${column.listOperationResult})
## 1. 处理 Swagger 注解
@Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end) @Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
## 2. 处理 Excel 导出
#if ("$!column.dictType" != "")##处理枚举值
@ExcelProperty(value = "${column.columnComment}", converter = DictConvert.class)
@DictFormat("${column.dictType}") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
#else
@ExcelProperty("${column.columnComment}")
#end
## 3. 处理字段定义
private ${column.javaType} ${column.javaField}; private ${column.javaType} ${column.javaField};
#end #end

View File

@ -3,24 +3,20 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePac
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import java.util.*; import java.util.*;
import javax.validation.constraints.*;
## 处理 BigDecimal 字段的引入
import java.util.*;
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.javaType} == "BigDecimal") #if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal; import java.math.BigDecimal;
#break #break
#end #end
#if (${column.javaType} == "LocalDateTime")
import java.time.LocalDateTime;
#break
#end #end
#end ## 处理 LocalDateTime 字段的引入
import javax.validation.constraints.*;
## 处理 Date 字段的引入
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult} #if ((${column.createOperation} || ${column.updateOperation}) && ${column.javaType} == "LocalDateTime")
&& ${column.javaType} == "LocalDateTime")## 时间类型
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
#break #break
#end #end
#end #end
@ -29,16 +25,25 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO; import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
#end #end
/** @Schema(description = "${sceneEnum.name} - ${table.classComment}新增/修改 Request VO")
* ${table.classComment} Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data @Data
public class ${sceneEnum.prefixClass}${table.className}BaseVO { public class ${sceneEnum.prefixClass}${table.className}SaveReqVO {
## 逐个处理字段
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult})##通用操作 #if (${column.createOperation} || ${column.updateOperation})
#parse("codegen/java/controller/vo/_column.vm") ## 1. 处理 Swagger 注解
@Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
#if (!${column.nullable})
## 2. 处理 Validator 参数校验
#if (${column.javaType} == 'String')
@NotEmpty(message = "${column.columnComment}不能为空")
#else
@NotNull(message = "${column.columnComment}不能为空")
#end
#end
## 3. 处理字段定义
private ${column.javaType} ${column.javaField};
#end #end
#end #end

View File

@ -1,30 +0,0 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
## 处理 Date 字段的引入
#foreach ($column in $columns)
#if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult})
&& ${column.javaType} == "LocalDateTime")## 时间类型
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
#break
#end
#end
@Schema(description = "${sceneEnum.name} - ${table.classComment}更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ${sceneEnum.prefixClass}${table.className}UpdateReqVO extends ${sceneEnum.prefixClass}${table.className}BaseVO {
#foreach ($column in $columns)
#if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult}))##不是通用字段
#parse("codegen/java/controller/vo/_column.vm")
#end
#end
}

View File

@ -1,36 +0,0 @@
package ${basePackage}.module.${table.moduleName}.convert.${table.businessName};
import java.util.*;
import ${PageResultClassName};
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*;
import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
/**
* ${table.classComment} Convert
*
* @author ${table.author}
*/
@Mapper
public interface ${table.className}Convert {
${table.className}Convert INSTANCE = Mappers.getMapper(${table.className}Convert.class);
${table.className}DO convert(${sceneEnum.prefixClass}${table.className}CreateReqVO bean);
${table.className}DO convert(${sceneEnum.prefixClass}${table.className}UpdateReqVO bean);
${sceneEnum.prefixClass}${table.className}RespVO convert(${table.className}DO bean);
List<${sceneEnum.prefixClass}${table.className}RespVO> convertList(List<${table.className}DO> list);
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType != 2 )
PageResult<${sceneEnum.prefixClass}${table.className}RespVO> convertPage(PageResult<${table.className}DO> page);
#end
List<${sceneEnum.prefixClass}${table.className}ExcelVO> convertList02(List<${table.className}DO> list);
}

View File

@ -57,14 +57,14 @@ public interface ${table.className}Mapper extends BaseMapperX<${table.className}
.orderByDesc(${table.className}DO::getId));## 大多数情况下id 倒序 .orderByDesc(${table.className}DO::getId));## 大多数情况下id 倒序
} }
#else
#end
default List<${table.className}DO> selectList(${sceneEnum.prefixClass}${table.className}ListReqVO reqVO) { default List<${table.className}DO> selectList(${sceneEnum.prefixClass}${table.className}ListReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<${table.className}DO>() return selectList(new LambdaQueryWrapperX<${table.className}DO>()
#listCondition() #listCondition()
.orderByDesc(${table.className}DO::getId));## 大多数情况下id 倒序 .orderByDesc(${table.className}DO::getId));## 大多数情况下id 倒序
} }
#end
## 特殊:树表专属逻辑 ## 特殊:树表专属逻辑
#if ( $table.templateType == 2 ) #if ( $table.templateType == 2 )

View File

@ -24,14 +24,14 @@ public interface ${table.className}Service {
* @param createReqVO 创建信息 * @param createReqVO 创建信息
* @return 编号 * @return 编号
*/ */
${primaryColumn.javaType} create${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO); ${primaryColumn.javaType} create${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO);
/** /**
* 更新${table.classComment} * 更新${table.classComment}
* *
* @param updateReqVO 更新信息 * @param updateReqVO 更新信息
*/ */
void update${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO); void update${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO);
/** /**
* 删除${table.classComment} * 删除${table.classComment}
@ -57,8 +57,7 @@ public interface ${table.className}Service {
* @return ${table.classComment}分页 * @return ${table.classComment}分页
*/ */
PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO); PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO);
#else
#end
/** /**
* 获得${table.classComment}列表 * 获得${table.classComment}列表
* *
@ -66,6 +65,7 @@ public interface ${table.className}Service {
* @return ${table.classComment}列表 * @return ${table.classComment}列表
*/ */
List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO); List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO);
#end
## 特殊:主子表专属逻辑 ## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables) #foreach ($subTable in $subTables)

View File

@ -14,8 +14,8 @@ import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.bu
#end #end
import ${PageResultClassName}; import ${PageResultClassName};
import ${PageParamClassName}; import ${PageParamClassName};
import ${BeanUtils};
import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert;
import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper; import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper;
## 特殊:主子表专属逻辑 ## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables) #foreach ($subTable in $subTables)
@ -49,9 +49,9 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 ) #if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
#end #end
public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) { public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO) {
// 插入 // 插入
${table.className}DO ${classNameVar} = ${table.className}Convert.INSTANCE.convert(createReqVO); ${table.className}DO ${classNameVar} = BeanUtils.toBean(createReqVO, ${table.className}DO.class);
${classNameVar}Mapper.insert(${classNameVar}); ${classNameVar}Mapper.insert(${classNameVar});
## 特殊:主子表专属逻辑(非 ERP 模式) ## 特殊:主子表专属逻辑(非 ERP 模式)
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 ) #if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
@ -78,11 +78,11 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 ) #if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
#end #end
public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) { public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO) {
// 校验存在 // 校验存在
validate${simpleClassName}Exists(updateReqVO.getId()); validate${simpleClassName}Exists(updateReqVO.getId());
// 更新 // 更新
${table.className}DO updateObj = ${table.className}Convert.INSTANCE.convert(updateReqVO); ${table.className}DO updateObj = BeanUtils.toBean(updateReqVO, ${table.className}DO.class);
${classNameVar}Mapper.updateById(updateObj); ${classNameVar}Mapper.updateById(updateObj);
## 特殊:主子表专属逻辑(非 ERP 模式) ## 特殊:主子表专属逻辑(非 ERP 模式)
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11) #if ( $subTables && $subTables.size() > 0 && $table.templateType != 11)
@ -151,12 +151,12 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
public PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) { public PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) {
return ${classNameVar}Mapper.selectPage(pageReqVO); return ${classNameVar}Mapper.selectPage(pageReqVO);
} }
#else
#end
@Override @Override
public List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO) { public List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO) {
return ${classNameVar}Mapper.selectList(listReqVO); return ${classNameVar}Mapper.selectList(listReqVO);
} }
#end
## 特殊:主子表专属逻辑 ## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables) #foreach ($subTable in $subTables)

View File

@ -77,15 +77,15 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest {
@Test @Test
public void testCreate${simpleClassName}_success() { public void testCreate${simpleClassName}_success() {
// 准备参数 // 准备参数
${sceneEnum.prefixClass}${table.className}CreateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}CreateReqVO.class); ${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class).setId(null);
// 调用 // 调用
${primaryColumn.javaType} ${classNameVar}Id = ${classNameVar}Service.create${simpleClassName}(reqVO); ${primaryColumn.javaType} ${classNameVar}Id = ${classNameVar}Service.create${simpleClassName}(createReqVO);
// 断言 // 断言
assertNotNull(${classNameVar}Id); assertNotNull(${classNameVar}Id);
// 校验记录的属性是否正确 // 校验记录的属性是否正确
${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(${classNameVar}Id); ${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(${classNameVar}Id);
assertPojoEquals(reqVO, ${classNameVar}); assertPojoEquals(createReqVO, ${classNameVar});
} }
@Test @Test
@ -94,24 +94,24 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest {
${table.className}DO db${simpleClassName} = randomPojo(${table.className}DO.class); ${table.className}DO db${simpleClassName} = randomPojo(${table.className}DO.class);
${classNameVar}Mapper.insert(db${simpleClassName});// @Sql: 先插入出一条存在的数据 ${classNameVar}Mapper.insert(db${simpleClassName});// @Sql: 先插入出一条存在的数据
// 准备参数 // 准备参数
${sceneEnum.prefixClass}${table.className}UpdateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}UpdateReqVO.class, o -> { ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class, o -> {
o.setId(db${simpleClassName}.getId()); // 设置更新的 ID o.setId(db${simpleClassName}.getId()); // 设置更新的 ID
}); });
// 调用 // 调用
${classNameVar}Service.update${simpleClassName}(reqVO); ${classNameVar}Service.update${simpleClassName}(updateReqVO);
// 校验是否更新正确 // 校验是否更新正确
${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(reqVO.getId()); // 获取最新的 ${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, ${classNameVar}); assertPojoEquals(updateReqVO, ${classNameVar});
} }
@Test @Test
public void testUpdate${simpleClassName}_notExists() { public void testUpdate${simpleClassName}_notExists() {
// 准备参数 // 准备参数
${sceneEnum.prefixClass}${table.className}UpdateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}UpdateReqVO.class); ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class);
// 调用, 并断言异常 // 调用, 并断言异常
assertServiceException(() -> ${classNameVar}Service.update${simpleClassName}(reqVO), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS); assertServiceException(() -> ${classNameVar}Service.update${simpleClassName}(updateReqVO), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS);
} }
@Test @Test
@ -151,8 +151,7 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest {
assertEquals(1, pageResult.getList().size()); assertEquals(1, pageResult.getList().size());
assertPojoEquals(db${simpleClassName}, pageResult.getList().get(0)); assertPojoEquals(db${simpleClassName}, pageResult.getList().get(0));
} }
#else
#end
@Test @Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGet${simpleClassName}List() { public void testGet${simpleClassName}List() {
@ -164,5 +163,6 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest {
assertEquals(1, list.size()); assertEquals(1, list.size());
assertPojoEquals(db${simpleClassName}, list.get(0)); assertPojoEquals(db${simpleClassName}, list.get(0));
} }
#end
} }

View File

@ -1,34 +1,36 @@
-- 将该建表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/create_tables.sql 文件里 -- 将该建表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/create_tables.sql 文件里
CREATE TABLE IF NOT EXISTS "${table.tableName.toLowerCase()}" ( CREATE TABLE IF NOT EXISTS "${table.tableName.toLowerCase()}" (
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.javaType} == 'Long') #if (${column.javaType} == 'Long')
#set ($dataType='bigint') #set ($dataType='bigint')
#elseif (${column.javaType} == 'Integer') #elseif (${column.javaType} == 'Integer')
#set ($dataType='int') #set ($dataType='int')
#elseif (${column.javaType} == 'Boolean') #elseif (${column.javaType} == 'Boolean')
#set ($dataType='bit') #set ($dataType='bit')
#elseif (${column.javaType} == 'Date') #elseif (${column.javaType} == 'Date')
#set ($dataType='datetime') #set ($dataType='datetime')
#else #else
#set ($dataType='varchar') #set ($dataType='varchar')
#end #end
#if (${column.primaryKey})##处理主键 #if (${column.primaryKey})##处理主键
"${column.javaField}"#if (${column.javaType} == 'String') ${dataType} NOT NULL#else ${dataType} NOT NULL GENERATED BY DEFAULT AS IDENTITY#end, "${column.javaField}"#if (${column.javaType} == 'String') ${dataType} NOT NULL#else ${dataType} NOT NULL GENERATED BY DEFAULT AS IDENTITY#end,
#else #else
#if (${column.columnName} == 'create_time') #if (${column.columnName} == 'create_time')
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
#elseif (${column.columnName} == 'update_time') #elseif (${column.columnName} == 'update_time')
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
#elseif (${column.columnName} == 'creator' || ${column.columnName} == 'updater') #elseif (${column.columnName} == 'creator' || ${column.columnName} == 'updater')
"${column.columnName}" ${dataType} DEFAULT '', "${column.columnName}" ${dataType} DEFAULT '',
#elseif (${column.columnName} == 'deleted') #elseif (${column.columnName} == 'deleted')
"deleted" bit NOT NULL DEFAULT FALSE, "deleted" bit NOT NULL DEFAULT FALSE,
#else #elseif (${column.columnName} == 'tenantId')
"${column.columnName.toLowerCase()}" ${dataType}#if (${column.nullable} == false) NOT NULL#end, "tenant_id" bigint NOT NULL DEFAULT 0,
#end #else
"${column.columnName.toLowerCase()}" ${dataType}#if (${column.nullable} == false) NOT NULL#end,
#end
#end #end
#end #end
PRIMARY KEY ("${primaryColumn.columnName.toLowerCase()}") PRIMARY KEY ("${primaryColumn.columnName.toLowerCase()}")
) COMMENT '${table.tableComment}'; ) COMMENT '${table.tableComment}';
-- 将该删表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/clean.sql 文件里 -- 将该删表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/clean.sql 文件里