zl程序教程

您现在的位置是:首页 >  后端

当前栏目

SpringBoot入门-批量操作优化

SpringBoot批量入门 操作 优化
2023-09-11 14:16:57 时间

批量选择处理是很多项目都会用到的常用功能。像人员角色选择,人员部门选择,人员门禁选择等。下图所示,左边是门禁列表,右边是人员列表,选择一个门禁,然后批量选择人员,选中的人员可以出入该门禁。

对于这个功能一般怎么实现呢? 

先看数据库设计,由于是多对多的结构,需要建张中间表

 接下去删除door_id对应用户

delete from user_door where door_id = ?

再批量添加记录

insert into user_door(?,?,?)

如上图选择了两个人,所以这条sql要执行两次。

相信大部分人对于该功能的实现是这样的,简单易懂,对于很多场景来说确实有效。但这样设计有什么问题呢?

我有一次去一家大公司参与项目的开发,他们有一千多号人,加一个人到门禁的操作要一分钟,因为要执行一千多次插入操作,我们知道插入操作是很慢的,特别是加索引的情况下,需要重建索引就更慢了。

如果我们再加个需求,给新增或者删除的人员发站内信告诉他权限的变更,那上面的设计就实现不了了,有没有更好的方案呢?

这个时候我们可以从数学中找点思路,大家应该都学习过集合,看下图

 A集合就是新的用户id,B集合就是老的用户id,那新增用户就是A与B的差集(横线部分),删除用户就是B与A的差集(竖线部分),AB的交集就是不变区域。那用代码怎么实现呢?

//为了清晰我用名字代替id
//newUsers是当前选中的人员
List<String> newUsers = Arrays.asList("张三", "王五");
//oldUsers是存在数据库中的老数据
List<String> oldUsers = Arrays.asList("张三", "李四");
//计算新增人员
List<String> addUsers = new ArrayList<>(newUsers);
addUsers.removeAll(oldUsers);
//计算删除人员
List<String> removeUsers = new ArrayList<>(oldUsers);
removeUsers.removeAll(newUsers);
System.out.println(addUsers); //王五老的数据没有,所以是新增的
System.out.println(removeUsers); //李四没被选中,应该被删除

输出结果:

与预期一致,现在得到了新增用户和删除用户,可以分别发站内信通知了,同时插入新增用户,删除对应删除用户就行了,比如今天新来一个同事,对应门禁新增一个用户,只需要插入一条记录就可以,而不需要重新插入上千条记录,效率特别高。