代码生成器:主子表,支持多个从字段 50%

This commit is contained in:
zhijiantianya@gmail.com
2023-11-08 21:00:34 +08:00
parent 2afc2caf1d
commit 2f6456e2b0
48 changed files with 916 additions and 147 deletions

View File

@@ -44,9 +44,10 @@ public class CodegenUpdateReqVO {
|| getParentMenuId() != null;
}
// TODO 芋艿:这里有问题哈;
@AssertTrue(message = "关联的子表与字段不能为空")
public boolean isSubValid() {
return ObjectUtil.notEqual(getTemplateType(), CodegenTemplateTypeEnum.MASTER_SUB)
return ObjectUtil.notEqual(getTemplateType(), CodegenTemplateTypeEnum.SUB)
|| (getSubTableId() != null && getSubColumnId() != null);
}

View File

@@ -0,0 +1,90 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo02;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.*;
import cn.iocoder.yudao.module.infra.convert.demo02.InfraDemoStudentConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo02.InfraDemoStudentDO;
import cn.iocoder.yudao.module.infra.service.demo02.InfraDemoStudentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 学生")
@RestController
@RequestMapping("/infra/demo-student")
@Validated
public class InfraDemoStudentController {
@Resource
private InfraDemoStudentService demoStudentService;
@PostMapping("/create")
@Operation(summary = "创建学生")
@PreAuthorize("@ss.hasPermission('infra:demo-student:create')")
public CommonResult<Long> createDemoStudent(@Valid @RequestBody InfraDemoStudentCreateReqVO createReqVO) {
return success(demoStudentService.createDemoStudent(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新学生")
@PreAuthorize("@ss.hasPermission('infra:demo-student:update')")
public CommonResult<Boolean> updateDemoStudent(@Valid @RequestBody InfraDemoStudentUpdateReqVO updateReqVO) {
demoStudentService.updateDemoStudent(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除学生")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:demo-student:delete')")
public CommonResult<Boolean> deleteDemoStudent(@RequestParam("id") Long id) {
demoStudentService.deleteDemoStudent(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得学生")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('infra:demo-student:query')")
public CommonResult<InfraDemoStudentRespVO> getDemoStudent(@RequestParam("id") Long id) {
InfraDemoStudentDO demoStudent = demoStudentService.getDemoStudent(id);
return success(InfraDemoStudentConvert.INSTANCE.convert(demoStudent));
}
@GetMapping("/page")
@Operation(summary = "获得学生分页")
@PreAuthorize("@ss.hasPermission('infra:demo-student:query')")
public CommonResult<PageResult<InfraDemoStudentRespVO>> getDemoStudentPage(@Valid InfraDemoStudentPageReqVO pageVO) {
PageResult<InfraDemoStudentDO> pageResult = demoStudentService.getDemoStudentPage(pageVO);
return success(InfraDemoStudentConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@Operation(summary = "导出学生 Excel")
@PreAuthorize("@ss.hasPermission('infra:demo-student:export')")
@OperateLog(type = EXPORT)
public void exportDemoStudentExcel(@Valid InfraDemoStudentExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<InfraDemoStudentDO> list = demoStudentService.getDemoStudentList(exportReqVO);
// 导出 Excel
List<InfraDemoStudentExcelVO> datas = InfraDemoStudentConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "学生.xls", "数据", InfraDemoStudentExcelVO.class, datas);
}
}

View File

@@ -0,0 +1 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo02;

View File

@@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo02.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo02.InfraDemoStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo02.InfraDemoStudentAddressDO;
/**
* 学生 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class InfraDemoStudentBaseVO {
private List<InfraDemoStudentContactDO> demoStudentContacts;
private InfraDemoStudentAddressDO demoStudentAddress;
}

View File

@@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo02.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 学生创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfraDemoStudentCreateReqVO extends InfraDemoStudentBaseVO {
}

View File

@@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo02.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import com.alibaba.excel.annotation.ExcelProperty;
/**
* 学生 Excel VO
*
* @author 芋道源码
*/
@Data
public class InfraDemoStudentExcelVO {
@ExcelProperty("编号")
private Long id;
}

View File

@@ -0,0 +1,12 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo02.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
@Schema(description = "管理后台 - 学生 Excel 导出 Request VO参数和 InfraDemoStudentPageReqVO 是一致的")
@Data
public class InfraDemoStudentExportReqVO {
}

View File

@@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo02.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
@Schema(description = "管理后台 - 学生分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfraDemoStudentPageReqVO extends PageParam {
}

View File

@@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo02.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
@Schema(description = "管理后台 - 学生 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfraDemoStudentRespVO extends InfraDemoStudentBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
}

View File

@@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo02.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 学生更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfraDemoStudentUpdateReqVO extends InfraDemoStudentBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "编号不能为空")
private Long id;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.infra.convert.demo02;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.InfraDemoStudentCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.InfraDemoStudentExcelVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.InfraDemoStudentRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.InfraDemoStudentUpdateReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo02.InfraDemoStudentDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 学生 Convert
*
* @author 芋道源码
*/
@Mapper
public interface InfraDemoStudentConvert {
InfraDemoStudentConvert INSTANCE = Mappers.getMapper(InfraDemoStudentConvert.class);
InfraDemoStudentDO convert(InfraDemoStudentCreateReqVO bean);
InfraDemoStudentDO convert(InfraDemoStudentUpdateReqVO bean);
InfraDemoStudentRespVO convert(InfraDemoStudentDO bean);
List<InfraDemoStudentRespVO> convertList(List<InfraDemoStudentDO> list);
PageResult<InfraDemoStudentRespVO> convertPage(PageResult<InfraDemoStudentDO> page);
List<InfraDemoStudentExcelVO> convertList02(List<InfraDemoStudentDO> list);
}

View File

@@ -119,16 +119,23 @@ public class CodegenTableDO extends BaseDO {
// ========== 主子表相关字段 ==========
/**
* 表的编号
* 表的编号
*
* 关联 {@link CodegenTableDO#getId()}
*/
private Long subTableId;
private Long masterTableId;
/**
* 子表关联字段编号
* 【自己】子表关联主表的字段编号
*
* 关联 {@link CodegenColumnDO#getId()}
*/
private Long subColumnId;
private Long subJoinColumnId;
/**
* 主表与子表是否一对多
*
* true一对多
* false一对一
*/
private Boolean subJoinMany;
}

View File

@@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo02;
import lombok.*;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生地址 DO
*
* @author 芋道源码
*/
@TableName("infra_demo_student_address")
@KeySequence("infra_demo_student_address_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InfraDemoStudentAddressDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 学生编号
*/
private Long studentId;
/**
* 明细
*/
private String detail;
}

View File

@@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo02;
import lombok.*;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生联系人 DO
*
* @author 芋道源码
*/
@TableName("infra_demo_student_contact")
@KeySequence("infra_demo_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InfraDemoStudentContactDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 学生编号
*/
private Long studentId;
/**
* 名字
*/
private String name;
}

View File

@@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo02;
import lombok.*;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生 DO
*
* @author 芋道源码
*/
@TableName("infra_demo_student")
@KeySequence("infra_demo_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InfraDemoStudentDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
}

View File

@@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo02;
import java.util.*;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo02.InfraDemoStudentAddressDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 学生地址 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraDemoStudentAddressMapper extends BaseMapperX<InfraDemoStudentAddressDO> {
default InfraDemoStudentAddressDO selectByStudentId(Long studentId) {
return selectOne(InfraDemoStudentAddressDO::getStudentId, studentId);
}
default List<InfraDemoStudentAddressDO> selectListByStudentId(List<Long> studentIds) {
return selectList(InfraDemoStudentAddressDO::getStudentId, studentIds);
}
default int deleteByStudentId(Long studentId) {
return delete(InfraDemoStudentAddressDO::getStudentId, studentId);
}
}

View File

@@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo02;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo02.InfraDemoStudentContactDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 学生联系人 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraDemoStudentContactMapper extends BaseMapperX<InfraDemoStudentContactDO> {
default List<InfraDemoStudentContactDO> selectListByStudentId(Long studentId) {
return selectList(InfraDemoStudentContactDO::getStudentId, studentId);
}
default List<InfraDemoStudentContactDO> selectListByStudentId(List<Long> studentIds) {
return selectList(InfraDemoStudentContactDO::getStudentId, studentIds);
}
default int deleteByStudentId(Long studentId) {
return delete(InfraDemoStudentContactDO::getStudentId, studentId);
}
}

View File

@@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo02;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.InfraDemoStudentExportReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.InfraDemoStudentPageReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo02.InfraDemoStudentDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 学生 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraDemoStudentMapper extends BaseMapperX<InfraDemoStudentDO> {
default PageResult<InfraDemoStudentDO> selectPage(InfraDemoStudentPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<InfraDemoStudentDO>()
.orderByDesc(InfraDemoStudentDO::getId));
}
default List<InfraDemoStudentDO> selectList(InfraDemoStudentExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<InfraDemoStudentDO>()
.orderByDesc(InfraDemoStudentDO::getId));
}
}

View File

@@ -12,9 +12,10 @@ import lombok.Getter;
@Getter
public enum CodegenTemplateTypeEnum {
CRUD(1), // 单表(增删改查)
ONE(1), // 单表(增删改查)
TREE(2), // 树表(增删改查)
MASTER_SUB(3), // 主子表
MASTER(10), // 主子表 - 主表
SUB(11), // 主子表 - 子表
;
/**

View File

@@ -238,13 +238,14 @@ public class CodegenServiceImpl implements CodegenService {
// 校验子表是否已经存在
CodegenTableDO subTable = null;
List<CodegenColumnDO> subColumns = null;
if (table.getSubTableId() != null) {
subTable = codegenTableMapper.selectById(table.getSubTableId());
subColumns = codegenColumnMapper.selectListByTableId(table.getSubTableId());
if (table.getMasterTableId() != null) {
subTable = codegenTableMapper.selectById(table.getMasterTableId());
subColumns = codegenColumnMapper.selectListByTableId(table.getMasterTableId());
}
// 执行生成
return codegenEngine.execute(table, columns, subTable, subColumns);
// return codegenEngine.execute(table, columns, subTable, subColumns);
return codegenEngine.execute(table, columns, null, null);
}
@Override

View File

@@ -118,7 +118,7 @@ public class CodegenBuilder {
table.setClassName(upperFirst(toCamelCase(subAfter(tableName, '_', false))));
// 去除结尾的表,作为类描述
table.setClassComment(StrUtil.removeSuffixIgnoreCase(table.getTableComment(), ""));
table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType());
table.setTemplateType(CodegenTemplateTypeEnum.ONE.getType());
}
public List<CodegenColumnDO> buildColumns(Long tableId, List<TableField> tableFields) {

View File

@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.infra.service.codegen.inner;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
@@ -186,12 +187,12 @@ public class CodegenEngine {
*
* @param table 表定义
* @param columns table 的字段定义数组
* @param subTable 子表定义,当且仅当主子表时使用
* @param subColumns subTable 的字段定义数组
* @param subTables 子表数组,当且仅当主子表时使用
* @param subColumnsList subTables 的字段定义数组
* @return 生成的代码key 是路径value 是对应代码
*/
public Map<String, String> execute(CodegenTableDO table, List<CodegenColumnDO> columns,
CodegenTableDO subTable, List<CodegenColumnDO> subColumns) {
List<CodegenTableDO> subTables, List<List<CodegenColumnDO>> subColumnsList) {
// 创建 bindingMap
Map<String, Object> bindingMap = new HashMap<>(globalBindingMap);
bindingMap.put("table", table);
@@ -212,27 +213,51 @@ public class CodegenEngine {
bindingMap.put("permissionPrefix", table.getModuleName() + ":" + simpleClassNameStrikeCase);
// 特殊:主子表专属逻辑
if (subTable != null) {
if (CollUtil.isNotEmpty(subTables)) {
// 创建 bindingMap
bindingMap.put("subTable", subTable);
bindingMap.put("subColumns", subColumns);
bindingMap.put("subColumn", CollectionUtils.findFirst(subColumns, // 关联的字段
column -> Objects.equals(column.getId(), table.getSubColumnId())));
// className 相关
String subSimpleClassName = removePrefix(subTable.getClassName(), upperFirst(subTable.getModuleName()));
bindingMap.put("subSimpleClassName", subSimpleClassName);
bindingMap.put("subClassNameVar", lowerFirst(subSimpleClassName)); // 将 DictType 转换成 dictType用于变量
bindingMap.put("subTables", subTables);
bindingMap.put("subColumnsList", subColumnsList);
List<CodegenColumnDO> subJoinColumns = new ArrayList<>();
List<String> subSimpleClassNames = new ArrayList<>();
List<String> subClassNameVars = new ArrayList<>();
for (int i = 0; i < subTables.size(); i++) {
CodegenTableDO subTable = subTables.get(i);
List<CodegenColumnDO> subColumns = subColumnsList.get(i);
subJoinColumns.add(CollectionUtils.findFirst(subColumns, // 关联的字段
column -> Objects.equals(column.getId(), subTable.getSubJoinColumnId())));
// className 相关
String subSimpleClassName = removePrefix(subTable.getClassName(), upperFirst(subTable.getModuleName()));
subSimpleClassNames.add(subSimpleClassName);
subClassNameVars.add(lowerFirst(subSimpleClassName)); // 将 DictType 转换成 dictType用于变量
}
bindingMap.put("subJoinColumns", subJoinColumns);
bindingMap.put("subSimpleClassNames", subSimpleClassNames);
bindingMap.put("subClassNameVars", subClassNameVars);
}
// 执行生成
Map<String, String> templates = getTemplates(table.getTemplateType(), table.getFrontType());
Map<String, String> result = Maps.newLinkedHashMapWithExpectedSize(templates.size()); // 有序
templates.forEach((vmPath, filePath) -> {
filePath = formatFilePath(filePath, bindingMap);
String content = templateEngine.getTemplate(vmPath).render(bindingMap);
// 去除字段后面多余的 , 逗号
content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }");
result.put(filePath, content);
// 特殊:主子表专属逻辑
if (isSubTemplate(vmPath)) {
for (int i = 0; i < subTables.size(); i++) {
bindingMap.put("subIndex", i);
// TODO 芋艿:这块需要优化下逻辑
String newFilePath = formatFilePath(filePath, bindingMap);
String content = templateEngine.getTemplate(vmPath).render(bindingMap);
// 去除字段后面多余的 , 逗号
content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }");
result.put(newFilePath, content);
bindingMap.remove("subIndex");
}
} else {
filePath = formatFilePath(filePath, bindingMap);
String content = templateEngine.getTemplate(vmPath).render(bindingMap);
// 去除字段后面多余的 , 逗号
content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }");
result.put(filePath, content);
}
});
return result;
}
@@ -242,7 +267,7 @@ public class CodegenEngine {
templates.putAll(SERVER_TEMPLATES);
templates.putAll(FRONT_TEMPLATES.row(frontType));
// 特殊:主子表专属逻辑
if (ObjUtil.notEqual(templateType, CodegenTemplateTypeEnum.MASTER_SUB.getType())) {
if (ObjUtil.notEqual(templateType, CodegenTemplateTypeEnum.MASTER.getType())) {
templates.remove(javaTemplatePath("dal/do_sub"));
templates.remove(javaTemplatePath("dal/mapper_sub"));
}
@@ -266,8 +291,11 @@ public class CodegenEngine {
filePath = StrUtil.replace(filePath, "${table.businessName}", table.getBusinessName());
filePath = StrUtil.replace(filePath, "${table.className}", table.getClassName());
// 特殊:主子表专属逻辑
CodegenTableDO subTable = (CodegenTableDO) bindingMap.get("subTable");
if (subTable != null) {
Integer subIndex = (Integer) bindingMap.get("subIndex");
if (subIndex != null) {
CodegenTableDO subTable = ((List<CodegenTableDO>) bindingMap.get("subTables")).get(subIndex);
filePath = StrUtil.replace(filePath, "${subTable.moduleName}", subTable.getModuleName());
filePath = StrUtil.replace(filePath, "${subTable.businessName}", subTable.getBusinessName());
filePath = StrUtil.replace(filePath, "${subTable.className}", subTable.getClassName());
}
return filePath;
@@ -336,4 +364,8 @@ public class CodegenEngine {
private static String vue3VbenTemplatePath(String path) {
return "codegen/vue3_vben/" + path + ".vm";
}
private static boolean isSubTemplate(String path) {
return path.contains("_sub");
}
}

View File

@@ -0,0 +1,68 @@
package cn.iocoder.yudao.module.infra.service.demo02;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.InfraDemoStudentCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.InfraDemoStudentExportReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.InfraDemoStudentPageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.InfraDemoStudentUpdateReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo02.InfraDemoStudentDO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* 学生 Service 接口
*
* @author 芋道源码
*/
public interface InfraDemoStudentService {
/**
* 创建学生
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createDemoStudent(@Valid InfraDemoStudentCreateReqVO createReqVO);
/**
* 更新学生
*
* @param updateReqVO 更新信息
*/
void updateDemoStudent(@Valid InfraDemoStudentUpdateReqVO updateReqVO);
/**
* 删除学生
*
* @param id 编号
*/
void deleteDemoStudent(Long id);
/**
* 获得学生
*
* @param id 编号
* @return 学生
*/
InfraDemoStudentDO getDemoStudent(Long id);
/**
* 获得学生分页
*
* @param pageReqVO 分页查询
* @return 学生分页
*/
PageResult<InfraDemoStudentDO> getDemoStudentPage(InfraDemoStudentPageReqVO pageReqVO);
/**
* 获得学生列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 学生列表
*/
List<InfraDemoStudentDO> getDemoStudentList(InfraDemoStudentExportReqVO exportReqVO);
}

View File

@@ -0,0 +1,107 @@
package cn.iocoder.yudao.module.infra.service.demo02;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.infra.controller.admin.demo02.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo02.InfraDemoStudentDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.convert.demo02.InfraDemoStudentConvert;
import cn.iocoder.yudao.module.infra.dal.mysql.demo02.InfraDemoStudentMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.demo02.InfraDemoStudentContactMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.demo02.InfraDemoStudentAddressMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
/**
* 学生 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class InfraDemoStudentServiceImpl implements InfraDemoStudentService {
@Resource
private InfraDemoStudentMapper demoStudentMapper;
@Resource
private InfraDemoStudentContactMapper demoStudentContactMapper;
@Resource
private InfraDemoStudentAddressMapper demoStudentAddressMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createDemoStudent(InfraDemoStudentCreateReqVO createReqVO) {
// 插入
InfraDemoStudentDO demoStudent = InfraDemoStudentConvert.INSTANCE.convert(createReqVO);
demoStudentMapper.insert(demoStudent);
// 插入子表(学生联系人)
createReqVO.getDemoStudentContacts().forEach(o -> o.setStudentId(demoStudent.getId()));
demoStudentContactMapper.insertBatch(createReqVO.getDemoStudentContacts());
// 插入子表(学生地址)
createReqVO.getDemoStudentAddress().setStudentId(demoStudent.getId());
demoStudentAddressMapper.insert(createReqVO.getDemoStudentAddress());
// 返回
return demoStudent.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateDemoStudent(InfraDemoStudentUpdateReqVO updateReqVO) {
// 校验存在
validateDemoStudentExists(updateReqVO.getId());
// 更新
InfraDemoStudentDO updateObj = InfraDemoStudentConvert.INSTANCE.convert(updateReqVO);
demoStudentMapper.updateById(updateObj);
// 更新子表(学生联系人)
demoStudentContactMapper.deleteByStudentId(updateReqVO.getId());
updateReqVO.getDemoStudentContacts().forEach(o -> o.setStudentId(updateReqVO.getId()));
demoStudentContactMapper.insertBatch(updateReqVO.getDemoStudentContacts());
// 更新子表(学生地址)
updateReqVO.getDemoStudentAddress().setStudentId(updateReqVO.getId());
demoStudentAddressMapper.updateById(updateReqVO.getDemoStudentAddress());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteDemoStudent(Long id) {
// 校验存在
validateDemoStudentExists(id);
// 删除
demoStudentMapper.deleteById(id);
// 删除子表(学生联系人)
demoStudentContactMapper.deleteByStudentId(id);
// 删除子表(学生地址)
demoStudentAddressMapper.deleteByStudentId(id);
}
private void validateDemoStudentExists(Long id) {
if (demoStudentMapper.selectById(id) == null) {
throw exception(DEMO_STUDENT_NOT_EXISTS);
}
}
@Override
public InfraDemoStudentDO getDemoStudent(Long id) {
return demoStudentMapper.selectById(id);
}
@Override
public PageResult<InfraDemoStudentDO> getDemoStudentPage(InfraDemoStudentPageReqVO pageReqVO) {
return demoStudentMapper.selectPage(pageReqVO);
}
@Override
public List<InfraDemoStudentDO> getDemoStudentList(InfraDemoStudentExportReqVO exportReqVO) {
return demoStudentMapper.selectList(exportReqVO);
}
}

View File

@@ -76,16 +76,6 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
return success(${table.className}Convert.INSTANCE.convert(${classNameVar}));
}
@GetMapping("/list")
@Operation(summary = "获得${table.classComment}列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end
public CommonResult<List<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}List(@RequestParam("ids") Collection<${primaryColumn.javaType}> ids) {
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(ids);
return success(${table.className}Convert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@Operation(summary = "获得${table.classComment}分页")
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end

View File

@@ -23,7 +23,7 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
#end
#end
## 特殊:主子表专属逻辑
#if ( $subTable )
#foreach ($subTable in $subTables)
import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
#end
@@ -41,8 +41,14 @@ public class ${sceneEnum.prefixClass}${table.className}BaseVO {
#end
#end
## 特殊:主子表专属逻辑
#if ( $subTable )
private List<${subTable.className}DO> ${subClassNameVar}s;
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#if ( $subTable.subJoinMany)
private List<${subTable.className}DO> ${subClassNameVars.get($index)}s;
#else
private ${subTable.className}DO ${subClassNameVars.get($index)};
#end
#end
}

View File

@@ -1,3 +1,5 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
package ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName};
import lombok.*;

View File

@@ -1,3 +1,7 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subJoinColumnsList.get($subIndex))##当前字段数组
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
package ${basePackage}.module.${subTable.moduleName}.dal.mysql.${subTable.businessName};
import java.util.*;
@@ -6,7 +10,6 @@ import ${BaseMapperClassName};
import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
import org.apache.ibatis.annotations.Mapper;
#set ($SubColumnName = $subColumn.javaField.substring(0,1).toUpperCase() + ${subColumn.javaField.substring(1)})##首字母大写
/**
* ${subTable.classComment} Mapper
*
@@ -15,12 +18,23 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ${subTable.className}Mapper extends BaseMapperX<${subTable.className}DO> {
default List<${subTable.className}DO> selectListBy${SubColumnName}(${subColumn.javaType} ${subColumn.javaField}) {
return selectList(${subTable.className}DO::get${SubColumnName}, ${subColumn.javaField});
#if ( $subTable.subJoinMany)
default List<${subTable.className}DO> selectListBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return selectList(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField});
}
default List<${subTable.className}DO> selectListBy${SubColumnName}(List<${subColumn.javaType}> ${subColumn.javaField}s) {
return selectList(${subTable.className}DO::get${SubColumnName}, ${subColumn.javaField}s);
#else
default ${subTable.className}DO selectBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return selectOne(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField});
}
#end
default List<${subTable.className}DO> selectListBy${SubJoinColumnName}(List<${subJoinColumn.javaType}> ${subJoinColumn.javaField}s) {
return selectList(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField}s);
}
default int deleteBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return delete(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField});
}
}

View File

@@ -43,14 +43,6 @@ public interface ${table.className}Service {
*/
${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id);
/**
* 获得${table.classComment}列表
*
* @param ids 编号
* @return ${table.classComment}列表
*/
List<${table.className}DO> get${simpleClassName}List(Collection<${primaryColumn.javaType}> ids);
/**
* 获得${table.classComment}分页
*
@@ -67,4 +59,30 @@ public interface ${table.className}Service {
*/
List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO);
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
#if ( $subTable.subJoinMany )
/**
* 获得${subTable.classComment}列表
*
* @param ${subJoinColumn.javaField} ${subJoinColumn.columnComment}
* @return ${subTable.classComment}列表
*/
List<${subTable.className}DO> get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField});
#else
/**
* 获得${subTable.classComment}
*
* @param ${subJoinColumn.javaField} ${subJoinColumn.columnComment}
* @return ${subTable.classComment}
*/
${subTable.className}DO get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField});
#end
#end
}

View File

@@ -3,6 +3,7 @@ package ${basePackage}.module.${table.moduleName}.service.${table.businessName};
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*;
@@ -16,8 +17,9 @@ import ${PageResultClassName};
import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert;
import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper;
## 特殊:主子表专属逻辑
#if( $subTable )
import ${basePackage}.module.${subTable.moduleName}.dal.mysql.${subTable.businessName}.${subClassNameVar}Mapper;
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
import ${basePackage}.module.${subTable.moduleName}.dal.mysql.${subTable.businessName}.${subTable.className}Mapper;
#end
import static ${ServiceExceptionUtilClassName}.exception;
@@ -38,40 +40,85 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
@Resource
private ${table.className}Mapper ${classNameVar}Mapper;
## 特殊:主子表专属逻辑
#if( $subTable )
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
@Resource
private ${subTable.className}Mapper ${subClassNameVar}Mapper;
private ${subTable.className}Mapper ${subClassNameVars.get($index)}Mapper;
#end
@Override
## 特殊:主子表专属逻辑
#if ( $subTables.size() > 0)
@Transactional(rollbackFor = Exception.class)
#end
public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) {
// 插入
${table.className}DO ${classNameVar} = ${table.className}Convert.INSTANCE.convert(createReqVO);
${classNameVar}Mapper.insert(${classNameVar});
## 特殊:主子表专属逻辑
#if( $subTable )
// 插入子表
${subClassNameVar}Mapper.insertBatch(createReqVO.get${subSimpleClassName}s);
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
// 插入子表($subTable.classComment
#if ( $subTable.subJoinMany)
createReqVO.get${subSimpleClassNames.get($index)}s().forEach(o -> o.set$SubJoinColumnName(${classNameVar}.getId()));
${subClassNameVars.get($index)}Mapper.insertBatch(createReqVO.get${subSimpleClassNames.get($index)}s());
#else
createReqVO.get${subSimpleClassNames.get($index)}().set$SubJoinColumnName(${classNameVar}.getId());
${subClassNameVars.get($index)}Mapper.insert(createReqVO.get${subSimpleClassNames.get($index)}());
#end
#end
// 返回
return ${classNameVar}.getId();
}
@Override
## 特殊:主子表专属逻辑
#if ( $subTables.size() > 0)
@Transactional(rollbackFor = Exception.class)
#end
public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) {
// 校验存在
validate${simpleClassName}Exists(updateReqVO.getId());
// 更新
${table.className}DO updateObj = ${table.className}Convert.INSTANCE.convert(updateReqVO);
${classNameVar}Mapper.updateById(updateObj);
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
// 更新子表($subTable.classComment
#if ( $subTable.subJoinMany)
${subClassNameVars.get($index)}Mapper.deleteBy${SubJoinColumnName}(updateReqVO.getId());
updateReqVO.get${subSimpleClassNames.get($index)}s().forEach(o -> o.set$SubJoinColumnName(updateReqVO.getId()));
${subClassNameVars.get($index)}Mapper.insertBatch(updateReqVO.get${subSimpleClassNames.get($index)}s());
#else
updateReqVO.get${subSimpleClassNames.get($index)}().set$SubJoinColumnName(updateReqVO.getId());
${subClassNameVars.get($index)}Mapper.updateById(updateReqVO.get${subSimpleClassNames.get($index)}());
#end
#end
}
@Override
## 特殊:主子表专属逻辑
#if ( $subTables.size() > 0)
@Transactional(rollbackFor = Exception.class)
#end
public void delete${simpleClassName}(${primaryColumn.javaType} id) {
// 校验存在
validate${simpleClassName}Exists(id);
// 删除
${classNameVar}Mapper.deleteById(id);
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
// 删除子表($subTable.classComment
${subClassNameVars.get($index)}Mapper.deleteBy${SubJoinColumnName}(id);
#end
}
private void validate${simpleClassName}Exists(${primaryColumn.javaType} id) {
@@ -85,14 +132,6 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
return ${classNameVar}Mapper.selectById(id);
}
@Override
public List<${table.className}DO> get${simpleClassName}List(Collection<${primaryColumn.javaType}> ids) {
if (CollUtil.isEmpty(ids)) {
return ListUtil.empty();
}
return ${classNameVar}Mapper.selectBatchIds(ids);
}
@Override
public PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) {
return ${classNameVar}Mapper.selectPage(pageReqVO);