二次查询父子表并组装

发布时间 2023-07-06 10:34:17作者: 豆苗稀

二次查询数据库,获取父表和子表的相关数据

List fathers = fatherRepo.findSomeList();
List fatherIds = fathers.stream().map(Father::getId).collect(toList);
List children = childRepo.findByFatherIdsIn(fatherIds);

注:oracle的in字句限制1000。MySQL限制了SQL语句的最大长度,可以认为对in语句没有限制。sqlserver对in语句没有限制。

子表数据挂载到父表对象的属性上

二次查询数据库获取父子表数据后,需要在java代码中,将子表数据挂载到父表对象的属性上。

java代码有三种实现方式:

  1. 双重for循环
for(father in fathers) {
  for(child in children) {
    if(child.parentId == father.id) {
      faher.children.add(child)
    }
  }
}
  1. lamda表达式形式的双重循环
fathers.each(father->{
  father.children.addAll(children.stream().filter(c -> c.parentId == father.id).collect())
})
  1. 两次循环
Map<ID,List<Child>> collect = children.stream().collect(Collectors.groupingBy(Child::getParentId))
fathers.each(father->{
  father.children.addAll(collect.getOrDefault(father.id, List.of()))
})

理论上方法3的两次循环时间复杂度为2n,方法1和2的时间复杂度为n^2. 但方法3需要引入多余的外部变量,编码不太方便。
方法2的编码方式最简洁。但据说lamda形式的循环略慢于普通for循环,因此执行速度可能略慢于方法1。
方法1的编码方式最灵活,方便增减其他逻辑代码。另外,不存在方法2和3中,有单行代码过长的问题。
在实际的javaweb开发中,优先使用方法1,其次2,再次3