Commit f5ea270be3a0580b53f10affeaa8dc066349cc6a

Authored by YunaiV
1 parent a2f70674

部门:优化父部门的校验逻辑,为代码生成做个铺垫?!

yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/dept/DeptIdEnum.java deleted
1 -package cn.iocoder.yudao.module.system.enums.dept;  
2 -  
3 -import lombok.AllArgsConstructor;  
4 -import lombok.Getter;  
5 -  
6 -/**  
7 - * 部门编号枚举  
8 - */  
9 -@Getter  
10 -@AllArgsConstructor  
11 -public enum DeptIdEnum {  
12 -  
13 - /**  
14 - * 根节点  
15 - */  
16 - ROOT(0L);  
17 -  
18 - private final Long id;  
19 -  
20 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java
@@ -21,6 +21,8 @@ import lombok.EqualsAndHashCode; @@ -21,6 +21,8 @@ import lombok.EqualsAndHashCode;
21 @EqualsAndHashCode(callSuper = true) 21 @EqualsAndHashCode(callSuper = true)
22 public class DeptDO extends TenantBaseDO { 22 public class DeptDO extends TenantBaseDO {
23 23
  24 + public static final Long PARENT_ID_ROOT = 0L;
  25 +
24 /** 26 /**
25 * 部门ID 27 * 部门ID
26 */ 28 */
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java
@@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.system.convert.dept.DeptConvert; @@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.system.convert.dept.DeptConvert;
11 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; 11 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
12 import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; 12 import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
13 import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; 13 import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
14 -import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum;  
15 import com.google.common.annotations.VisibleForTesting; 14 import com.google.common.annotations.VisibleForTesting;
16 import lombok.extern.slf4j.Slf4j; 15 import lombok.extern.slf4j.Slf4j;
17 import org.springframework.cache.annotation.CacheEvict; 16 import org.springframework.cache.annotation.CacheEvict;
@@ -42,14 +41,17 @@ public class DeptServiceImpl implements DeptService { @@ -42,14 +41,17 @@ public class DeptServiceImpl implements DeptService {
42 @Override 41 @Override
43 @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, 42 @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
44 allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 43 allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存
45 - public Long createDept(DeptCreateReqVO reqVO) {  
46 - // 校验正确性  
47 - if (reqVO.getParentId() == null) {  
48 - reqVO.setParentId(DeptIdEnum.ROOT.getId()); 44 + public Long createDept(DeptCreateReqVO createReqVO) {
  45 + if (createReqVO.getParentId() == null) {
  46 + createReqVO.setParentId(DeptDO.PARENT_ID_ROOT);
49 } 47 }
50 - validateForCreateOrUpdate(null, reqVO.getParentId(), reqVO.getName()); 48 + // 校验父部门的有效性
  49 + validateParentDept(null, createReqVO.getParentId());
  50 + // 校验部门名的唯一性
  51 + validateDeptNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
  52 +
51 // 插入部门 53 // 插入部门
52 - DeptDO dept = DeptConvert.INSTANCE.convert(reqVO); 54 + DeptDO dept = DeptConvert.INSTANCE.convert(createReqVO);
53 deptMapper.insert(dept); 55 deptMapper.insert(dept);
54 return dept.getId(); 56 return dept.getId();
55 } 57 }
@@ -57,14 +59,19 @@ public class DeptServiceImpl implements DeptService { @@ -57,14 +59,19 @@ public class DeptServiceImpl implements DeptService {
57 @Override 59 @Override
58 @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, 60 @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
59 allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 61 allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存
60 - public void updateDept(DeptUpdateReqVO reqVO) {  
61 - // 校验正确性  
62 - if (reqVO.getParentId() == null) {  
63 - reqVO.setParentId(DeptIdEnum.ROOT.getId()); 62 + public void updateDept(DeptUpdateReqVO updateReqVO) {
  63 + if (updateReqVO.getParentId() == null) {
  64 + updateReqVO.setParentId(DeptDO.PARENT_ID_ROOT);
64 } 65 }
65 - validateForCreateOrUpdate(reqVO.getId(), reqVO.getParentId(), reqVO.getName()); 66 + // 校验自己存在
  67 + validateDeptExists(updateReqVO.getId());
  68 + // 校验父部门的有效性
  69 + validateParentDept(updateReqVO.getId(), updateReqVO.getParentId());
  70 + // 校验部门名的唯一性
  71 + validateDeptNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
  72 +
66 // 更新部门 73 // 更新部门
67 - DeptDO updateObj = DeptConvert.INSTANCE.convert(reqVO); 74 + DeptDO updateObj = DeptConvert.INSTANCE.convert(updateReqVO);
68 deptMapper.updateById(updateObj); 75 deptMapper.updateById(updateObj);
69 } 76 }
70 77
@@ -82,15 +89,6 @@ public class DeptServiceImpl implements DeptService { @@ -82,15 +89,6 @@ public class DeptServiceImpl implements DeptService {
82 deptMapper.deleteById(id); 89 deptMapper.deleteById(id);
83 } 90 }
84 91
85 - private void validateForCreateOrUpdate(Long id, Long parentId, String name) {  
86 - // 校验自己存在  
87 - validateDeptExists(id);  
88 - // 校验父部门的有效性  
89 - validateParentDept(id, parentId);  
90 - // 校验部门名的唯一性  
91 - validateDeptNameUnique(id, parentId, name);  
92 - }  
93 -  
94 @VisibleForTesting 92 @VisibleForTesting
95 void validateDeptExists(Long id) { 93 void validateDeptExists(Long id) {
96 if (id == null) { 94 if (id == null) {
@@ -104,22 +102,36 @@ public class DeptServiceImpl implements DeptService { @@ -104,22 +102,36 @@ public class DeptServiceImpl implements DeptService {
104 102
105 @VisibleForTesting 103 @VisibleForTesting
106 void validateParentDept(Long id, Long parentId) { 104 void validateParentDept(Long id, Long parentId) {
107 - if (parentId == null || DeptIdEnum.ROOT.getId().equals(parentId)) { 105 + if (parentId == null || DeptDO.PARENT_ID_ROOT.equals(parentId)) {
108 return; 106 return;
109 } 107 }
110 - // 不能设置自己为父部门  
111 - if (parentId.equals(id)) { 108 + // 1. 不能设置自己为父部门
  109 + if (Objects.equals(id, parentId)) {
112 throw exception(DEPT_PARENT_ERROR); 110 throw exception(DEPT_PARENT_ERROR);
113 } 111 }
114 - // 父岗位不存在  
115 - DeptDO dept = deptMapper.selectById(parentId);  
116 - if (dept == null) { 112 + // 2. 父部门不存在
  113 + DeptDO parentDept = deptMapper.selectById(parentId);
  114 + if (parentDept == null) {
117 throw exception(DEPT_PARENT_NOT_EXITS); 115 throw exception(DEPT_PARENT_NOT_EXITS);
118 } 116 }
119 - // 父部门不能是原来的子部门  
120 - List<DeptDO> children = getChildDeptList(id);  
121 - if (children.stream().anyMatch(dept1 -> dept1.getId().equals(parentId))) {  
122 - throw exception(DEPT_PARENT_IS_CHILD); 117 + // 3. 递归校验父部门,如果父部门是自己的子部门,则报错,避免形成环路
  118 + if (id == null) { // id 为空,说明新增,不需要考虑环路
  119 + return;
  120 + }
  121 + for (int i = 0; i < Short.MAX_VALUE; i++) {
  122 + // 3.1 校验环路
  123 + parentId = parentDept.getParentId();
  124 + if (Objects.equals(id, parentId)) {
  125 + throw exception(DEPT_PARENT_IS_CHILD);
  126 + }
  127 + // 3.2 继续递归下一级父部门
  128 + if (parentId == null || DeptDO.PARENT_ID_ROOT.equals(parentId)) {
  129 + break;
  130 + }
  131 + parentDept = deptMapper.selectById(parentId);
  132 + if (parentDept == null) {
  133 + break;
  134 + }
123 } 135 }
124 } 136 }
125 137
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImplTest.java
@@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqV @@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqV
8 import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; 8 import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO;
9 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; 9 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
10 import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; 10 import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
11 -import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum;  
12 import org.junit.jupiter.api.Test; 11 import org.junit.jupiter.api.Test;
13 import org.springframework.context.annotation.Import; 12 import org.springframework.context.annotation.Import;
14 13
@@ -41,7 +40,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest { @@ -41,7 +40,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
41 public void testCreateDept() { 40 public void testCreateDept() {
42 // 准备参数 41 // 准备参数
43 DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> { 42 DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> {
44 - o.setParentId(DeptIdEnum.ROOT.getId()); 43 + o.setParentId(DeptDO.PARENT_ID_ROOT);
45 o.setStatus(randomCommonStatus()); 44 o.setStatus(randomCommonStatus());
46 }); 45 });
47 46
@@ -62,7 +61,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest { @@ -62,7 +61,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
62 // 准备参数 61 // 准备参数
63 DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { 62 DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> {
64 // 设置更新的 ID 63 // 设置更新的 ID
65 - o.setParentId(DeptIdEnum.ROOT.getId()); 64 + o.setParentId(DeptDO.PARENT_ID_ROOT);
66 o.setId(dbDeptDO.getId()); 65 o.setId(dbDeptDO.getId());
67 o.setStatus(randomCommonStatus()); 66 o.setStatus(randomCommonStatus());
68 }); 67 });