目录
- 写作背景
- 我和若依的前一部分相同思路
- 我的后续解决思路(不建议)
- 若依后续解决思路(建议)
- 若依后续解决思路举例
写作背景
平时我用case when then else end
的机会也不多,之前用它来做对select结果进行计算,例如:
select job,ename,(case job when 'MANAGER' then sal*1.1 when 'SALESMAN' then sal*1.5 else sal*1.8 end) as "newSal" from emp;
上面sql语句的作用是判断job字段的值,然后根据不同的值来计算薪水
今天我在看若依项目,看到里面对部门结构树的移动操作,虽然实际上是修改部门所属组织机构操作,但背后隐藏的是树中结构的移动操作,由于若依在定义部门表的时候添加了一个ancestors
字段,其实也就是path字段,存储的是从最高级到当前级别的路径id字符串组合(中间用英文逗号分隔),所以我们在更改某一个部门所属父级的时候,不仅要更新改部门的ancestors
字段,也要更新该部门所有子部门的所有ancestors
字段,我们看一下页面吧,如下:
按照上图可以看出,我们要将研发中心
下面的长沙分公司
移动到若依科技
下面,但是长沙分公司下面还有两个子级部门,按照上面的说法,我们不仅需要修改长沙分公司
的ancestors
字段(类型path,全路径id字符串组合),也要更新该部门所有子部门的所有ancestors
字段
我和若依的前一部分相同思路
先根据部门id找到长沙分公司
以前的ancestors
字段值,然后在获取长沙分公司
最新的ancestors
字段值(先获取到最新父级ancestors
字段值,再加上父级id,这就是长沙分公司
最新的ancestors
字段值了)
根据长沙分公司的id找到所有的子级数据,然后根据上面获取到长沙分公司
的新老ancestors
字段值进行replace替换
现在我们拿到了所有子级部门最新ancestors
字段值,代码逻辑如下:
List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
for (SysDept child : children)
{
child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
}
我的后续解决思路(不建议)
如果是我的话,我估计会根据部门id去挨个更新,这种方式会和数据库进行多次交互,所以不建议这么做
若依后续解决思路(建议)
直接使用一个update语句更新所有的数据,我们先来看一下代码吧,如下:
java代码:
List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
for (SysDept child : children)
{
child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
}
if (children.size() > 0)
{
deptMapper.updateDeptChildren(children);
}
sql文件.xml:
<update id="updateDeptChildren" parameterType="java.util.List">
update sys_dept set ancestors =
<foreach collection="depts" item="item" index="index"
separator=" " open="case dept_id" close="end">
when #{item.deptId} then #{item.ancestors}
</foreach>
where dept_id in
<foreach collection="depts" item="item" index="index"
separator="," open="(" close=")">
#{item.deptId}
</foreach>
</update>
我们来看一下具体的sql长啥样,如下:
update sys_dept set ancestors = case dept_id when ? then ? when ? then ? end where dept_id in ( ? , ? )
通过上面的sql可以看到,首先先通过where条件找到所有需要更新的数据,然后在更新的时候通过判断dept_id的值在决定ancestors的值,所以一句sql语句可以解决所有的子级分类更新问题,是不是很nice呢
目前若依持久层框架使用的是mybatis
,如果我们使用mybatis-plus
,那可以使用baseMapper.updateBatchById()
方法进行批量更新操作
若依后续解决思路举例
针对上面的情况我们举一个demo吧,假设原有数据长这样:
我们想把所有sex
值为男的age
值更新成20,sex
值等于女的age
值更新成18,sql语句如下:
update t_user
set age =
case sex
when "男" THEN 20
when "女" THEN 18
end
最终结果如下,愿望达成