Jelajahi Sumber

代码生成:增加更全的 tree 场景下的新增/修改校验

YunaiV 1 tahun lalu
induk
melakukan
01a55b93c2

+ 8 - 4
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java

@@ -324,10 +324,14 @@ public class CodegenEngine {
 
         // 特殊:树表专属逻辑
         if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) {
-            bindingMap.put("treeParentColumn", CollUtil.findOne(columns,
-                    column -> Objects.equals(column.getId(), table.getTreeParentColumnId())));
-            bindingMap.put("treeNameColumn", CollUtil.findOne(columns,
-                    column -> Objects.equals(column.getId(), table.getTreeNameColumnId())));
+            CodegenColumnDO treeParentColumn = CollUtil.findOne(columns,
+                    column -> Objects.equals(column.getId(), table.getTreeParentColumnId()));
+            bindingMap.put("treeParentColumn", treeParentColumn);
+            bindingMap.put("treeParentColumn_javaField_underlineCase", toUnderlineCase(treeParentColumn.getJavaField()));
+            CodegenColumnDO treeNameColumn = CollUtil.findOne(columns,
+                    column -> Objects.equals(column.getId(), table.getTreeNameColumnId()));
+            bindingMap.put("treeNameColumn", treeNameColumn);
+            bindingMap.put("treeNameColumn_javaField_underlineCase", toUnderlineCase(treeNameColumn.getJavaField()));
         }
 
         // 特殊:主子表专属逻辑

+ 5 - 0
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do.vm

@@ -28,6 +28,11 @@ import ${BaseDOClassName};
 @AllArgsConstructor
 public class ${table.className}DO extends BaseDO {
 
+## 特殊:树表专属逻辑
+#if ( $table.templateType == 2 )
+    public static final Long ${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT = 0L;
+
+#end
 #foreach ($column in $columns)
 #if (!${baseDOFields.contains(${column.javaField})})##排除 BaseDO 的字段
     /**

+ 8 - 3
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper.vm

@@ -68,9 +68,14 @@ public interface ${table.className}Mapper extends BaseMapperX<${table.className}
 
 ## 特殊:树表专属逻辑
 #if ( $table.templateType == 2 )
-#set ($ParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写
-    default Long selectCountBy${ParentJavaField}(${treeParentColumn.javaType} ${treeParentColumn.javaField}) {
-        return selectCount(${table.className}DO::get${ParentJavaField}, ${treeParentColumn.javaField});
+#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写
+#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写
+	default ${table.className}DO selectBy${TreeParentJavaField}And${TreeNameJavaField}(Long ${treeParentColumn.javaField}, String ${treeNameColumn.javaField}) {
+	    return selectOne(${table.className}DO::get${TreeParentJavaField}, ${treeParentColumn.javaField}, ${table.className}DO::get${TreeNameJavaField}, ${treeNameColumn.javaField});
+	}
+
+    default Long selectCountBy${TreeParentJavaField}(${treeParentColumn.javaType} ${treeParentColumn.javaField}) {
+        return selectCount(${table.className}DO::get${TreeParentJavaField}, ${treeParentColumn.javaField});
     }
 
 #end

+ 3 - 0
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/enums/errorcode.vm

@@ -4,4 +4,7 @@ ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS = new ErrorC
 ## 特殊:树表专属逻辑
 #if ( $table.templateType == 2 )
 ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_EXITS_CHILDREN = new ErrorCode(TODO 补充编号, "存在存在子${table.classComment},无法删除");
+ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_NOT_EXITS = new ErrorCode(TODO 补充编号,"父级${table.classComment}不存在");
+ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_ERROR = new ErrorCode(TODO 补充编号, "不能设置自己为父${table.classComment}");
+ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE = new ErrorCode(TODO 补充编号, "已经存在该${treeNameColumn.columnComment}的${table.classComment}");
 #end

+ 73 - 0
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm

@@ -50,6 +50,16 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
     @Transactional(rollbackFor = Exception.class)
 #end
     public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO) {
+## 特殊:树表专属逻辑
+#if ( $table.templateType == 2 )
+#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写
+#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写
+        // 校验${treeParentColumn.columnComment}的有效性
+        validateParent${simpleClassName}(null, createReqVO.get${TreeParentJavaField}());
+        // 校验${treeNameColumn.columnComment}的唯一性
+        validate${simpleClassName}${TreeNameJavaField}Unique(null, createReqVO.get${TreeParentJavaField}(), createReqVO.get${TreeNameJavaField}());
+
+#end
         // 插入
         ${table.className}DO ${classNameVar} = BeanUtils.toBean(createReqVO, ${table.className}DO.class);
         ${classNameVar}Mapper.insert(${classNameVar});
@@ -81,6 +91,16 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
     public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO) {
         // 校验存在
         validate${simpleClassName}Exists(updateReqVO.getId());
+## 特殊:树表专属逻辑
+#if ( $table.templateType == 2 )
+#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写
+#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写
+        // 校验${treeParentColumn.columnComment}的有效性
+        validateParent${simpleClassName}(updateReqVO.getId(), updateReqVO.get${TreeParentJavaField}());
+        // 校验${treeNameColumn.columnComment}的唯一性
+        validate${simpleClassName}${TreeNameJavaField}Unique(updateReqVO.getId(), updateReqVO.get${TreeParentJavaField}(), updateReqVO.get${TreeNameJavaField}());
+
+#end
         // 更新
         ${table.className}DO updateObj = BeanUtils.toBean(updateReqVO, ${table.className}DO.class);
         ${classNameVar}Mapper.updateById(updateObj);
@@ -140,6 +160,59 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
         }
     }
 
+## 特殊:树表专属逻辑
+#if ( $table.templateType == 2 )
+#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写
+#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写
+    private void validateParent${simpleClassName}(Long id, Long ${treeParentColumn.javaField}) {
+        if (${treeParentColumn.javaField} == null || ${simpleClassName}DO.${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT.equals(${treeParentColumn.javaField})) {
+            return;
+        }
+        // 1. 不能设置自己为父${table.classComment}
+        if (Objects.equals(id, ${treeParentColumn.javaField})) {
+            throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_ERROR);
+        }
+        // 2. 父${table.classComment}不存在
+        ${simpleClassName}DO parent${simpleClassName} = ${classNameVar}Mapper.selectById(${treeParentColumn.javaField});
+        if (parent${simpleClassName} == null) {
+            throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_NOT_EXITS);
+        }
+        // 3. 递归校验父${table.classComment},如果父${table.classComment}是自己的子${table.classComment},则报错,避免形成环路
+        if (id == null) { // id 为空,说明新增,不需要考虑环路
+            return;
+        }
+        for (int i = 0; i < Short.MAX_VALUE; i++) {
+            // 3.1 校验环路
+            ${treeParentColumn.javaField} = parent${simpleClassName}.get${TreeParentJavaField}();
+            if (Objects.equals(id, ${treeParentColumn.javaField})) {
+                throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_IS_CHILD);
+            }
+            // 3.2 继续递归下一级父${table.classComment}
+            if (${treeParentColumn.javaField} == null || ${simpleClassName}DO.${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT.equals(${treeParentColumn.javaField})) {
+                break;
+            }
+            parent${simpleClassName} = ${classNameVar}Mapper.selectById(${treeParentColumn.javaField});
+            if (parent${simpleClassName} == null) {
+                break;
+            }
+        }
+    }
+
+    private void validate${simpleClassName}${TreeNameJavaField}Unique(Long id, Long ${treeParentColumn.javaField}, String ${treeNameColumn.javaField}) {
+        ${simpleClassName}DO ${classNameVar} = ${classNameVar}Mapper.selectBy${TreeParentJavaField}And${TreeNameJavaField}(${treeParentColumn.javaField}, ${treeNameColumn.javaField});
+        if (${classNameVar} == null) {
+            return;
+        }
+        // 如果 id 为空,说明不用比较是否为相同 id 的${table.classComment}
+        if (id == null) {
+            throw exception(${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE);
+        }
+        if (ObjectUtil.notEqual(${classNameVar}.getId(), id)) {
+            throw exception(${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE);
+        }
+    }
+
+#end
     @Override
     public ${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id) {
         return ${classNameVar}Mapper.selectById(id);

+ 1 - 2
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineTest.java

@@ -51,8 +51,7 @@ public class CodegenEngineTest extends BaseMockitoUnitTest {
                 .setClassComment("学生").setAuthor("芋道源码")
                 .setTemplateType(CodegenTemplateTypeEnum.TREE.getType())
                 .setFrontType(CodegenFrontTypeEnum.VUE3.getType())
-                .setTreeParentColumnId(22L).setTreeNameColumnId(11L)
-                ;
+                .setTreeParentColumnId(22L).setTreeNameColumnId(11L);
         CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
                 .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
                 .setJavaType("Long").setJavaField("id").setExample("1024")

+ 1 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java

@@ -141,7 +141,7 @@ public class DeptServiceImpl implements DeptService {
         if (dept == null) {
             return;
         }
-        // 如果 id 为空,说明不用比较是否为相同 id 的岗位
+        // 如果 id 为空,说明不用比较是否为相同 id 的部门
         if (id == null) {
             throw exception(DEPT_NAME_DUPLICATE);
         }