使用Streams API通过子实体递归查找多级父节点及关联子实体
递归查询父实体及关联子实体实现方案
你已配置的双向关联可直接支撑以下实现,注意自关联场景下需将示例中的Parent/Child替换为你的实际实体类名。
需求1:从当前子实体出发向上递归遍历所有父实体至根节点
Java 9+ 实现(推荐)
直接使用三参数Stream.iterate方法迭代父节点,直到父节点为null(根节点的父节点为空)即可终止:
import java.util.Objects; import java.util.stream.Collectors; import java.util.List; // 方法写在你的实体类中即可,返回的列表按层级从直接父节点到根节点排序 public List<YourEntity> getAllParents() { // 若需要将当前实体也加入返回列表,可将第一个参数改为this,终止判断保留即可 return Stream.iterate(this.getParent(), Objects::nonNull, YourEntity::getParent) .collect(Collectors.toList()); }
Java 8 兼容实现
Java 8无三参数Stream.iterate,可通过递归拼接Stream实现:
import java.util.stream.Stream; import java.util.stream.Collectors; import java.util.List; // 私有递归生成父节点Stream private Stream<YourEntity> parentStream() { if (this.getParent() == null) { return Stream.empty(); } return Stream.concat(Stream.of(this.getParent()), this.getParent().parentStream()); } // 对外暴露的获取所有父节点方法 public List<YourEntity> getAllParents() { return parentStream().collect(Collectors.toList()); }
需求2:访问每一级父实体关联的全部子实体
拿到所有父节点列表后,直接通过flatMap展开每个父节点的子集合即可,也可自行遍历父节点列表分别处理每一级的子集合:
// 示例:收集所有上级父节点关联的全部子实体(包含各层级的同级节点) public List<YourEntity> getAllSiblingsFromUpperLevels() { return getAllParents().stream() // 若需要过滤掉当前实体自身,可在flatMap后加.filter(child -> !child.equals(this)) .flatMap(parent -> parent.getChildren().stream()) .collect(Collectors.toList()); }
注意事项
- 你配置的
children属性为FetchType.LAZY,需确保访问子集合时Hibernate会话未关闭,否则会抛出懒加载初始化异常。若需要脱离会话使用,可在初始查询当前实体时通过JOIN FETCH提前加载关联的父/子集合,非必要不建议修改为FetchType.EAGER。 - 若实体层级过深(超过千级),Java 8的递归写法可能出现栈溢出,可改为迭代循环写法规避。
内容的提问来源于stack exchange,提问作者SSJCODERNOT
相关产品推荐
相关产品推荐

