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 21 @EqualsAndHashCode(callSuper = true)
22 22 public class DeptDO extends TenantBaseDO {
23 23  
  24 + public static final Long PARENT_ID_ROOT = 0L;
  25 +
24 26 /**
25 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 11 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
12 12 import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
13 13 import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
14   -import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum;
15 14 import com.google.common.annotations.VisibleForTesting;
16 15 import lombok.extern.slf4j.Slf4j;
17 16 import org.springframework.cache.annotation.CacheEvict;
... ... @@ -42,14 +41,17 @@ public class DeptServiceImpl implements DeptService {
42 41 @Override
43 42 @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
44 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 55 deptMapper.insert(dept);
54 56 return dept.getId();
55 57 }
... ... @@ -57,14 +59,19 @@ public class DeptServiceImpl implements DeptService {
57 59 @Override
58 60 @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
59 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 75 deptMapper.updateById(updateObj);
69 76 }
70 77  
... ... @@ -82,15 +89,6 @@ public class DeptServiceImpl implements DeptService {
82 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 92 @VisibleForTesting
95 93 void validateDeptExists(Long id) {
96 94 if (id == null) {
... ... @@ -104,22 +102,36 @@ public class DeptServiceImpl implements DeptService {
104 102  
105 103 @VisibleForTesting
106 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 106 return;
109 107 }
110   - // 不能设置自己为父部门
111   - if (parentId.equals(id)) {
  108 + // 1. 不能设置自己为父部门
  109 + if (Objects.equals(id, parentId)) {
112 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 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 8 import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO;
9 9 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
10 10 import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
11   -import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum;
12 11 import org.junit.jupiter.api.Test;
13 12 import org.springframework.context.annotation.Import;
14 13  
... ... @@ -41,7 +40,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
41 40 public void testCreateDept() {
42 41 // 准备参数
43 42 DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> {
44   - o.setParentId(DeptIdEnum.ROOT.getId());
  43 + o.setParentId(DeptDO.PARENT_ID_ROOT);
45 44 o.setStatus(randomCommonStatus());
46 45 });
47 46  
... ... @@ -62,7 +61,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
62 61 // 准备参数
63 62 DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> {
64 63 // 设置更新的 ID
65   - o.setParentId(DeptIdEnum.ROOT.getId());
  64 + o.setParentId(DeptDO.PARENT_ID_ROOT);
66 65 o.setId(dbDeptDO.getId());
67 66 o.setStatus(randomCommonStatus());
68 67 });
... ...