Commit 01a55b93c2dc9019d85ea5548ba82d26c32476e5
1 parent
f5ea270b
代码生成:增加更全的 tree 场景下的新增/修改校验
Showing
7 changed files
with
99 additions
and
10 deletions
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 { | @@ -324,10 +324,14 @@ public class CodegenEngine { | ||
| 324 | 324 | ||
| 325 | // 特殊:树表专属逻辑 | 325 | // 特殊:树表专属逻辑 |
| 326 | if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { | 326 | if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { |
| 327 | - bindingMap.put("treeParentColumn", CollUtil.findOne(columns, | ||
| 328 | - column -> Objects.equals(column.getId(), table.getTreeParentColumnId()))); | ||
| 329 | - bindingMap.put("treeNameColumn", CollUtil.findOne(columns, | ||
| 330 | - column -> Objects.equals(column.getId(), table.getTreeNameColumnId()))); | 327 | + CodegenColumnDO treeParentColumn = CollUtil.findOne(columns, |
| 328 | + column -> Objects.equals(column.getId(), table.getTreeParentColumnId())); | ||
| 329 | + bindingMap.put("treeParentColumn", treeParentColumn); | ||
| 330 | + bindingMap.put("treeParentColumn_javaField_underlineCase", toUnderlineCase(treeParentColumn.getJavaField())); | ||
| 331 | + CodegenColumnDO treeNameColumn = CollUtil.findOne(columns, | ||
| 332 | + column -> Objects.equals(column.getId(), table.getTreeNameColumnId())); | ||
| 333 | + bindingMap.put("treeNameColumn", treeNameColumn); | ||
| 334 | + bindingMap.put("treeNameColumn_javaField_underlineCase", toUnderlineCase(treeNameColumn.getJavaField())); | ||
| 331 | } | 335 | } |
| 332 | 336 | ||
| 333 | // 特殊:主子表专属逻辑 | 337 | // 特殊:主子表专属逻辑 |
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do.vm
| @@ -28,6 +28,11 @@ import ${BaseDOClassName}; | @@ -28,6 +28,11 @@ import ${BaseDOClassName}; | ||
| 28 | @AllArgsConstructor | 28 | @AllArgsConstructor |
| 29 | public class ${table.className}DO extends BaseDO { | 29 | public class ${table.className}DO extends BaseDO { |
| 30 | 30 | ||
| 31 | +## 特殊:树表专属逻辑 | ||
| 32 | +#if ( $table.templateType == 2 ) | ||
| 33 | + public static final Long ${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT = 0L; | ||
| 34 | + | ||
| 35 | +#end | ||
| 31 | #foreach ($column in $columns) | 36 | #foreach ($column in $columns) |
| 32 | #if (!${baseDOFields.contains(${column.javaField})})##排除 BaseDO 的字段 | 37 | #if (!${baseDOFields.contains(${column.javaField})})##排除 BaseDO 的字段 |
| 33 | /** | 38 | /** |
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} | @@ -68,9 +68,14 @@ public interface ${table.className}Mapper extends BaseMapperX<${table.className} | ||
| 68 | 68 | ||
| 69 | ## 特殊:树表专属逻辑 | 69 | ## 特殊:树表专属逻辑 |
| 70 | #if ( $table.templateType == 2 ) | 70 | #if ( $table.templateType == 2 ) |
| 71 | -#set ($ParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写 | ||
| 72 | - default Long selectCountBy${ParentJavaField}(${treeParentColumn.javaType} ${treeParentColumn.javaField}) { | ||
| 73 | - return selectCount(${table.className}DO::get${ParentJavaField}, ${treeParentColumn.javaField}); | 71 | +#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写 |
| 72 | +#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写 | ||
| 73 | + default ${table.className}DO selectBy${TreeParentJavaField}And${TreeNameJavaField}(Long ${treeParentColumn.javaField}, String ${treeNameColumn.javaField}) { | ||
| 74 | + return selectOne(${table.className}DO::get${TreeParentJavaField}, ${treeParentColumn.javaField}, ${table.className}DO::get${TreeNameJavaField}, ${treeNameColumn.javaField}); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + default Long selectCountBy${TreeParentJavaField}(${treeParentColumn.javaType} ${treeParentColumn.javaField}) { | ||
| 78 | + return selectCount(${table.className}DO::get${TreeParentJavaField}, ${treeParentColumn.javaField}); | ||
| 74 | } | 79 | } |
| 75 | 80 | ||
| 76 | #end | 81 | #end |
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 | @@ -4,4 +4,7 @@ ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS = new ErrorC | ||
| 4 | ## 特殊:树表专属逻辑 | 4 | ## 特殊:树表专属逻辑 |
| 5 | #if ( $table.templateType == 2 ) | 5 | #if ( $table.templateType == 2 ) |
| 6 | ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_EXITS_CHILDREN = new ErrorCode(TODO 补充编号, "存在存在子${table.classComment},无法删除"); | 6 | ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_EXITS_CHILDREN = new ErrorCode(TODO 补充编号, "存在存在子${table.classComment},无法删除"); |
| 7 | +ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_NOT_EXITS = new ErrorCode(TODO 补充编号,"父级${table.classComment}不存在"); | ||
| 8 | +ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_ERROR = new ErrorCode(TODO 补充编号, "不能设置自己为父${table.classComment}"); | ||
| 9 | +ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE = new ErrorCode(TODO 补充编号, "已经存在该${treeNameColumn.columnComment}的${table.classComment}"); | ||
| 7 | #end | 10 | #end |
| 8 | \ No newline at end of file | 11 | \ No newline at end of file |
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 | @@ -50,6 +50,16 @@ public class ${table.className}ServiceImpl implements ${table.className}Service | ||
| 50 | @Transactional(rollbackFor = Exception.class) | 50 | @Transactional(rollbackFor = Exception.class) |
| 51 | #end | 51 | #end |
| 52 | public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO) { | 52 | public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO) { |
| 53 | +## 特殊:树表专属逻辑 | ||
| 54 | +#if ( $table.templateType == 2 ) | ||
| 55 | +#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写 | ||
| 56 | +#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写 | ||
| 57 | + // 校验${treeParentColumn.columnComment}的有效性 | ||
| 58 | + validateParent${simpleClassName}(null, createReqVO.get${TreeParentJavaField}()); | ||
| 59 | + // 校验${treeNameColumn.columnComment}的唯一性 | ||
| 60 | + validate${simpleClassName}${TreeNameJavaField}Unique(null, createReqVO.get${TreeParentJavaField}(), createReqVO.get${TreeNameJavaField}()); | ||
| 61 | + | ||
| 62 | +#end | ||
| 53 | // 插入 | 63 | // 插入 |
| 54 | ${table.className}DO ${classNameVar} = BeanUtils.toBean(createReqVO, ${table.className}DO.class); | 64 | ${table.className}DO ${classNameVar} = BeanUtils.toBean(createReqVO, ${table.className}DO.class); |
| 55 | ${classNameVar}Mapper.insert(${classNameVar}); | 65 | ${classNameVar}Mapper.insert(${classNameVar}); |
| @@ -81,6 +91,16 @@ public class ${table.className}ServiceImpl implements ${table.className}Service | @@ -81,6 +91,16 @@ public class ${table.className}ServiceImpl implements ${table.className}Service | ||
| 81 | public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO) { | 91 | public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO) { |
| 82 | // 校验存在 | 92 | // 校验存在 |
| 83 | validate${simpleClassName}Exists(updateReqVO.getId()); | 93 | validate${simpleClassName}Exists(updateReqVO.getId()); |
| 94 | +## 特殊:树表专属逻辑 | ||
| 95 | +#if ( $table.templateType == 2 ) | ||
| 96 | +#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写 | ||
| 97 | +#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写 | ||
| 98 | + // 校验${treeParentColumn.columnComment}的有效性 | ||
| 99 | + validateParent${simpleClassName}(updateReqVO.getId(), updateReqVO.get${TreeParentJavaField}()); | ||
| 100 | + // 校验${treeNameColumn.columnComment}的唯一性 | ||
| 101 | + validate${simpleClassName}${TreeNameJavaField}Unique(updateReqVO.getId(), updateReqVO.get${TreeParentJavaField}(), updateReqVO.get${TreeNameJavaField}()); | ||
| 102 | + | ||
| 103 | +#end | ||
| 84 | // 更新 | 104 | // 更新 |
| 85 | ${table.className}DO updateObj = BeanUtils.toBean(updateReqVO, ${table.className}DO.class); | 105 | ${table.className}DO updateObj = BeanUtils.toBean(updateReqVO, ${table.className}DO.class); |
| 86 | ${classNameVar}Mapper.updateById(updateObj); | 106 | ${classNameVar}Mapper.updateById(updateObj); |
| @@ -140,6 +160,59 @@ public class ${table.className}ServiceImpl implements ${table.className}Service | @@ -140,6 +160,59 @@ public class ${table.className}ServiceImpl implements ${table.className}Service | ||
| 140 | } | 160 | } |
| 141 | } | 161 | } |
| 142 | 162 | ||
| 163 | +## 特殊:树表专属逻辑 | ||
| 164 | +#if ( $table.templateType == 2 ) | ||
| 165 | +#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写 | ||
| 166 | +#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写 | ||
| 167 | + private void validateParent${simpleClassName}(Long id, Long ${treeParentColumn.javaField}) { | ||
| 168 | + if (${treeParentColumn.javaField} == null || ${simpleClassName}DO.${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT.equals(${treeParentColumn.javaField})) { | ||
| 169 | + return; | ||
| 170 | + } | ||
| 171 | + // 1. 不能设置自己为父${table.classComment} | ||
| 172 | + if (Objects.equals(id, ${treeParentColumn.javaField})) { | ||
| 173 | + throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_ERROR); | ||
| 174 | + } | ||
| 175 | + // 2. 父${table.classComment}不存在 | ||
| 176 | + ${simpleClassName}DO parent${simpleClassName} = ${classNameVar}Mapper.selectById(${treeParentColumn.javaField}); | ||
| 177 | + if (parent${simpleClassName} == null) { | ||
| 178 | + throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_NOT_EXITS); | ||
| 179 | + } | ||
| 180 | + // 3. 递归校验父${table.classComment},如果父${table.classComment}是自己的子${table.classComment},则报错,避免形成环路 | ||
| 181 | + if (id == null) { // id 为空,说明新增,不需要考虑环路 | ||
| 182 | + return; | ||
| 183 | + } | ||
| 184 | + for (int i = 0; i < Short.MAX_VALUE; i++) { | ||
| 185 | + // 3.1 校验环路 | ||
| 186 | + ${treeParentColumn.javaField} = parent${simpleClassName}.get${TreeParentJavaField}(); | ||
| 187 | + if (Objects.equals(id, ${treeParentColumn.javaField})) { | ||
| 188 | + throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_IS_CHILD); | ||
| 189 | + } | ||
| 190 | + // 3.2 继续递归下一级父${table.classComment} | ||
| 191 | + if (${treeParentColumn.javaField} == null || ${simpleClassName}DO.${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT.equals(${treeParentColumn.javaField})) { | ||
| 192 | + break; | ||
| 193 | + } | ||
| 194 | + parent${simpleClassName} = ${classNameVar}Mapper.selectById(${treeParentColumn.javaField}); | ||
| 195 | + if (parent${simpleClassName} == null) { | ||
| 196 | + break; | ||
| 197 | + } | ||
| 198 | + } | ||
| 199 | + } | ||
| 200 | + | ||
| 201 | + private void validate${simpleClassName}${TreeNameJavaField}Unique(Long id, Long ${treeParentColumn.javaField}, String ${treeNameColumn.javaField}) { | ||
| 202 | + ${simpleClassName}DO ${classNameVar} = ${classNameVar}Mapper.selectBy${TreeParentJavaField}And${TreeNameJavaField}(${treeParentColumn.javaField}, ${treeNameColumn.javaField}); | ||
| 203 | + if (${classNameVar} == null) { | ||
| 204 | + return; | ||
| 205 | + } | ||
| 206 | + // 如果 id 为空,说明不用比较是否为相同 id 的${table.classComment} | ||
| 207 | + if (id == null) { | ||
| 208 | + throw exception(${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE); | ||
| 209 | + } | ||
| 210 | + if (ObjectUtil.notEqual(${classNameVar}.getId(), id)) { | ||
| 211 | + throw exception(${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE); | ||
| 212 | + } | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | +#end | ||
| 143 | @Override | 216 | @Override |
| 144 | public ${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id) { | 217 | public ${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id) { |
| 145 | return ${classNameVar}Mapper.selectById(id); | 218 | return ${classNameVar}Mapper.selectById(id); |
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 { | @@ -51,8 +51,7 @@ public class CodegenEngineTest extends BaseMockitoUnitTest { | ||
| 51 | .setClassComment("学生").setAuthor("芋道源码") | 51 | .setClassComment("学生").setAuthor("芋道源码") |
| 52 | .setTemplateType(CodegenTemplateTypeEnum.TREE.getType()) | 52 | .setTemplateType(CodegenTemplateTypeEnum.TREE.getType()) |
| 53 | .setFrontType(CodegenFrontTypeEnum.VUE3.getType()) | 53 | .setFrontType(CodegenFrontTypeEnum.VUE3.getType()) |
| 54 | - .setTreeParentColumnId(22L).setTreeNameColumnId(11L) | ||
| 55 | - ; | 54 | + .setTreeParentColumnId(22L).setTreeNameColumnId(11L); |
| 56 | CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name()) | 55 | CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name()) |
| 57 | .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true) | 56 | .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true) |
| 58 | .setJavaType("Long").setJavaField("id").setExample("1024") | 57 | .setJavaType("Long").setJavaField("id").setExample("1024") |
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 { | @@ -141,7 +141,7 @@ public class DeptServiceImpl implements DeptService { | ||
| 141 | if (dept == null) { | 141 | if (dept == null) { |
| 142 | return; | 142 | return; |
| 143 | } | 143 | } |
| 144 | - // 如果 id 为空,说明不用比较是否为相同 id 的岗位 | 144 | + // 如果 id 为空,说明不用比较是否为相同 id 的部门 |
| 145 | if (id == null) { | 145 | if (id == null) { |
| 146 | throw exception(DEPT_NAME_DUPLICATE); | 146 | throw exception(DEPT_NAME_DUPLICATE); |
| 147 | } | 147 | } |