背景
所有的代码功能实现都是对业务需求的实现,脱离业务的展示肌肉方式不可行。
最近有个业务需求,因为B业务的数据来源于C表和D表。因为B中把C和D的ID存放到了一个字段,然后加了个类型字段进行了区分。
当C表和D表的数据删除后,B表的数据需要同步进行删除操作。
思路
1、最简单的方法。
直接在C表和D表的相关Service实现中,在删除的方法中增加对应的删除B业务的数据代码就可以了。
总结
简单、粗暴、高效(在开发的角度上来看),但是代码侵入性较大,后期维护拆分的时候有点痛苦。
2、使用切面。
在C和D的删除方法上使用注解,然后在注解里面更新。
总结
优秀,但是业务涉及面较窄,开发工作量相对较大一些。
3、使用定时器
总结
业务拆分,定时器里可以根据业务进行动态的调整,相对来讲,比较符合当前的业务。
解决
实现思路
回到我们的解决思路来:根据我们的业务来看,我们刚开始查询出来的数据是一个B列表对象。然后再去根据类型筛选出来对应的C和D有效数据,然后再使用当前B数据对象去匹配删除有效数据。剩下的都是无效数据,把无效数据批量删除就可以了。
伪代码
先上伪代码(翻译上面那段啰嗦的话)
//1、获取B的所有有效数据
List<B> listB= selectListB();
//2、分类,根据分类结果来查对应的C和D
List<Long,List<B>> map = listB.stream().collect(Collectors.groupingBy(B::getType));
//3、循环map 根据类型来查出对应的C和D的数据
map.forEach((k, v) -> {
if (类型==C) {
List<C> listC=selectListC(v->List<B>中获取相关的查询条件的CId)
//删除有效数据
listB.removeIf(listC对应的所有有效数据)
} else {
List<D> listD=selectListD(v->List<B>中获取相关的查询条件的DId)
//删除有效数据
listB.removeIf(listD对应的所有有效数据)
}
});
//4、批量删除 剩下来的listB就是无效数据了
deleteBatchB(listB)
在这个里面,主要是用到了stream的新的特性相关方法,主要就是用来批量删除子对象。这样剩下的战斗渣渣就可以使用批量删除,减少了和数据库的沟通次数了。
removeIf方法
着重介绍下removeIf方法。removeIf() 方法作用是用于删除所有满足特定条件的数组元素。
老规矩,先看源码
/**
* Removes all of the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @implSpec
* The default implementation traverses all elements of the collection using
* its {@link #iterator}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws NullPointerException if the specified filter is null
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @since 1.8
*/
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
方法说明
参数说明:
filter - 过滤器,判断元素是否要删除
返回值
如果元素被删除则返回 true。
使用场景
伪代码中的listB.removeIf(listC对应的所有有效数据)的这个的实现就用到了
代码
listB.removeIf(listC对应的所有有效数据)
//代码实现
listB.removeIf(e -> listC.stream().map(C::getId).collect(Collectors.toList()).contains(e.getTypeId()));
//说明:getTypeId这个是B中存放的C的主键ID
使用这个的好处,就是我们可以复用一个对象,打野中路,减少内存的输出伤害!
总结说明
代码是为业务服务的。没有最好的实现方法,只有最符合当前的业务模式的实现。