如何用PostgreSQL及Spring JPA/Hibernate关联父表与两无关子表获目标记录
父表关联多子表的查询解决方案
1. 获取总计13条目标记录
你需要的是C1、C2中匹配父表的记录集合(无重复合并),可通过以下两种方式实现:
方式一:原生SQL(JPA/Hibernate支持UNION ALL)
JPA原生SQL查询完全支持UNION ALL,直接编写如下语句即可:
SELECT p.*, c1.*, NULL AS c2_col1, NULL AS c2_col2, ... FROM parent p INNER JOIN child1 c1 ON p.id = c1.parent_id UNION ALL SELECT p.*, NULL AS c1_col1, NULL AS c1_col2, ..., c2.* FROM parent p INNER JOIN child2 c2 ON p.id = c2.parent_id;
注意:两个子查询的列数、数据类型必须一致,不存在的列用
NULL填充,需将示例中的c1_col1、c2_col2替换为实际字段名。
方式二:JPA Query + 代码合并
若不想用UNION,可分别查询两个子表关联父表的结果,再在业务代码中合并集合:
// 查询C1关联父表的所有记录 List<ParentChild1DTO> c1List = entityManager.createQuery( "SELECT new com.yourpackage.ParentChild1DTO(p, c1) FROM Parent p JOIN p.child1 c1", ParentChild1DTO.class ).getResultList(); // 查询C2关联父表的所有记录 List<ParentChild2DTO> c2List = entityManager.createQuery( "SELECT new com.yourpackage.ParentChild2DTO(p, c2) FROM Parent p JOIN p.child2 c2", ParentChild2DTO.class ).getResultList(); // 转换为统一DTO并合并 List<ParentChildCombinedDTO> resultList = new ArrayList<>(); resultList.addAll(convertToCombinedDTO(c1List)); resultList.addAll(convertToCombinedDTO(c2List));
需提前定义对应DTO类封装查询结果,
convertToCombinedDTO方法负责将不同子表的DTO转换为统一格式。
2. Limit 8时返回C1全部5条+ C2的3条记录
同样提供两种实现方式:
方式一:原生SQL
通过UNION ALL结合LIMIT控制,先取C1全部记录,再取C2前3条:
(SELECT p.*, c1.*, NULL AS c2_col1, NULL AS c2_col2, ... FROM parent p INNER JOIN child1 c1 ON p.id = c1.parent_id) UNION ALL (SELECT p.*, NULL AS c1_col1, NULL AS c1_col2, ..., c2.* FROM parent p INNER JOIN child2 c2 ON p.id = c2.parent_id LIMIT 3) LIMIT 8;
方式二:JPA Query + 代码控制
先查询C1全部5条记录,再查询C2前3条,合并后得到目标结果:
// 查询C1全部关联记录并转换为统一DTO List<ParentChildCombinedDTO> c1Result = convertToCombinedDTO( entityManager.createQuery( "SELECT new com.yourpackage.ParentChild1DTO(p, c1) FROM Parent p JOIN p.child1 c1", ParentChild1DTO.class ).getResultList() ); // 查询C2前3条关联记录并转换为统一DTO List<ParentChildCombinedDTO> c2Result = convertToCombinedDTO( entityManager.createQuery( "SELECT new com.yourpackage.ParentChild2DTO(p, c2) FROM Parent p JOIN p.child2 c2", ParentChild2DTO.class ).setMaxResults(3) .getResultList() ); // 合并最终结果 List<ParentChildCombinedDTO> finalResult = new ArrayList<>(); finalResult.addAll(c1Result); finalResult.addAll(c2Result);
内容的提问来源于stack exchange,提问作者oldcode
相关产品推荐
相关产品推荐

