目录
1、业务背景介绍
我们在实际实现的开发业务之中,有这样的场景,比如在设置角色的操作页面,我们可能取消部分角色、或者新增授权一部分角色等等。以及本文讲讨论的实际业务场景,把课程研讨内容分派给全班学员,和指定部分分组学员。
一般开发人员是比较粗暴的实现方式直接删除原来的记录,重新添加一遍所有的记录。这样操作虽然确实可以实现此功能;可能出现如下弊端:可能我就没有做任何操作,结果程序把所有的记录都删除一次;或者我仅仅只变化了很小一部分结果也是给我全部删除一次。这样不仅仅没有满足最小原则改动应该变动的数据,同时这样频繁的操作数据库会让数据库产生很多binlog日志。MySQL主从复制时使用的binlog日志,它记录了所有的 DDL 和 DML 语句(除了数据查询语句select、show等),以事件形式记录,还包含语句所执行的消耗时间。
如果这样粗暴的实现数据记录的删除和新增,如果操作频率比较高;产生的binlog日志会很多。
2、最小化产生Binlog代码实现
操作整体流程图
2.1、从小组切换到班级分组
//从已有小组切换到班级小组,此时需要删除原来的小组,新增一个班级小组(可能是更新删除字段)
// 查询当前研讨主题 以前有用的分组信息 并执行删除以前小组分组信息
List<Map<String, Object>> groupIdOldActiveMapList = discussTopicExtendMapper
.getDiscussTopicGroupIdsActiveOrDeleteList(clazzId, discussTopicAddEditDTO.getId(), BusinessConstants.CONSTANT_ZERO);
if (groupIdOldActiveMapList.size() > 0) {
List<Map<String, Object>> groupIdDeleteMapList = new ArrayList<>();
for (Map<String, Object> oldroupMap : groupIdOldActiveMapList) {
oldroupMap.put("updateTime", currentTime);
oldroupMap.put("updateBy", userId);
oldroupMap.put("deleteTime", currentTime);
groupIdDeleteMapList.add(oldroupMap);
}
//软删除研讨对应的分组信息
if (groupIdDeleteMapList.size() > 0) {
discussTopicExtendMapper.updateBatchDeleteTopicGroupList(groupIdDeleteMapList);
}
}
//执行添加或者恢复以前班级研讨小组
// === 获得是否有班级分组
List<Map<String, Object>> clazzGroupIdsMapList = discussTopicExtendMapper
.getDiscussTopicClazzGroupIdsList(clazzId, discussTopicAddEditDTO.getId(), BusinessConstants.CONSTANT_ZERO);
if (clazzGroupIdsMapList.size() > 0) {
//恢复以前的班级研讨小组
List<Map<String, Object>> clazzGroupRecoveryMapList = new ArrayList<>();
for (Map<String, Object> clazzGroupMap : clazzGroupIdsMapList) {
clazzGroupMap.put("updateTime", currentTime);
clazzGroupMap.put("updateBy", userId);
clazzGroupMap.put("deleteTime", BusinessConstants.CONSTANT_ZERO);
clazzGroupRecoveryMapList.add(clazzGroupMap);
}
//软删除研讨对应的分组信息
if (clazzGroupRecoveryMapList.size() > 0) {
discussTopicExtendMapper.updateBatchDeleteTopicGroupList(clazzGroupRecoveryMapList);
}
} else {
//添加一个班级研讨小组
List<Map<String, Object>> batchDiscussTopicGroupList = new ArrayList<>();
Map<String, Object> discussTopicGroup = generateAddDiscussTopicGroupMap(
discussTopic.getId(), BusinessConstants.CONSTANT_ZERO, clazzId,
clazz.getProgramId(), userId, currentTime, BusinessConstants.CONSTANT_ZERO);
batchDiscussTopicGroupList.add(discussTopicGroup);
discussTopicExtendMapper.insertBatchDiscussTopicGroupList(batchDiscussTopicGroupList);
}
2.2、从班级分组切换到选择研讨小组
/**
* 添加或者更新研讨的分组
*
* @param discussTopicAddEditDTO
* @param userId
* @param discussTopicId
* @param programId
* @param clazzId
* @param currentTime
* @param groupIdCurrentList
*/
private void addOrUpdateDiscussTopicGroups(DiscussTopicAddEditDTO discussTopicAddEditDTO, Long userId, Long discussTopicId, Long programId, Long clazzId, Long currentTime, List<Long> groupIdCurrentList) {
// 查询当前研讨主题 以前有用的分组信息
List<Map<String, Object>> groupIdOldActiveMapList = discussTopicExtendMapper
.getDiscussTopicGroupIdsActiveOrDeleteList(clazzId, discussTopicAddEditDTO.getId(), BusinessConstants.CONSTANT_ZERO);
List<Long> groupIdOldList = groupIdOldActiveMapList.stream().map(
mapItem -> (Long) mapItem.get("group_id")).collect(Collectors.toList());
//差集 groupIdCurrentList-groupIdOldList 获得本次新新增加的研讨小组
List<Long> newAddGroupIdsList = groupIdCurrentList.stream()
.filter(groupId -> !groupIdOldList.contains(groupId))
.collect(Collectors.toList());
List<Map<String, Object>> batchDiscussTopicGroupList = new ArrayList<>();
//针对新增加的研讨小组可能有前面删除,此时仅仅只需更新信息
//获得已经删除研讨主题小组
List<Map<String, Object>> groupIdOldDeleteMapList = discussTopicExtendMapper
.getDiscussTopicGroupIdsActiveOrDeleteList(clazzId, discussTopicAddEditDTO.getId(), BusinessConstants.CONSTANT_ONE);
//恢复以前删除 当前需要添加的小组
List<Map<String, Object>> groupIdRecoveryDeleteMapList = new ArrayList<>();
for (Long groupId : newAddGroupIdsList) {
boolean deletedFlag = false;
for (Map<String, Object> groupIdOldDeleteMap : groupIdOldDeleteMapList) {
Long oldGroupId = (Long) groupIdOldDeleteMap.get("group_id");
if (groupId.equals(oldGroupId)) {
deletedFlag = true;
groupIdOldDeleteMap.put("updateTime", currentTime);
groupIdOldDeleteMap.put("updateBy", userId);
groupIdOldDeleteMap.put("deleteTime", BusinessConstants.CONSTANT_ZERO);
groupIdRecoveryDeleteMapList.add(groupIdOldDeleteMap);
}
}
//新增的不在已经删除的内容
if (!deletedFlag) {
Map<String, Object> discussTopicGroup = generateAddDiscussTopicGroupMap(
discussTopicId, groupId, clazzId,
programId, userId, currentTime, BusinessConstants.CONSTANT_ZERO);
batchDiscussTopicGroupList.add(discussTopicGroup);
}
}
//批量添加研讨小组之中不在以前删除内容
if (batchDiscussTopicGroupList.size() > 0) {
discussTopicExtendMapper.insertBatchDiscussTopicGroupList(batchDiscussTopicGroupList);
}
//恢复已经已经删除的但是在当前研讨话题新增的
if (groupIdRecoveryDeleteMapList.size() > 0) {
discussTopicExtendMapper.updateBatchDeleteTopicGroupList(groupIdRecoveryDeleteMapList);
}
// 差集 ( groupIdOldList -groupIdCurrentList )
List<Long> deleteGroupIdsList = groupIdOldList.stream()
.filter(item -> !groupIdCurrentList.contains(item)).collect(Collectors.toList());
List<Map<String, Object>> groupIdDeleteMapList = new ArrayList<>();
for (Long groupId : deleteGroupIdsList) {
for (Map<String, Object> oldroupMap : groupIdOldActiveMapList) {
Long oldGroupId = (Long) oldroupMap.get("group_id");
if (groupId.equals(oldGroupId)) {
oldroupMap.put("updateTime", currentTime);
oldroupMap.put("updateBy", userId);
oldroupMap.put("deleteTime", currentTime);
groupIdDeleteMapList.add(oldroupMap);
}
}
}
//软删除研讨对应的分组信息
if (groupIdDeleteMapList.size() > 0) {
discussTopicExtendMapper.updateBatchDeleteTopicGroupList(groupIdDeleteMapList);
}
}
3、成果展现
4、总结
本功能实现案例,通过综合运用集合的差集,下图所示:
及动态切换已经逻辑删除的记录进行有效回收♻️利用;实现了 最小的产生Binlog日志;同时减少了数据库的操作,同时实现的业务的功能。