Java HQL递归,我该怎么做?
我有一个树结构,其中每个Java HQL递归,我该怎么做?,java,hibernate,orm,recursion,hql,Java,Hibernate,Orm,Recursion,Hql,我有一个树结构,其中每个节点都有一个父节点和一个集子节点。每个节点都有一个字符串标题,我想在其中进行查询,选择设置标题,作为此节点和所有父节点的标题。如何编写此查询 对单个标题的查询是这样的,但正如我所说的,我希望对整个家长分支进行扩展 SELECT node.title FROM Node node WHERE node.id = :id 干杯 Nik您不能使用HQL执行递归查询。如前所述,它甚至不是标准的SQL。您有两个选择: 编写特定于供应商的递归本机 进行多个查询。例如: // ob
节点都有一个父节点和一个集子节点。每个节点都有一个字符串标题
,我想在其中进行查询,选择设置标题
,作为此节点和所有父节点的标题。如何编写此查询
对单个标题的查询是这样的,但正如我所说的,我希望对整个家长分支进行扩展
SELECT node.title FROM Node node WHERE node.id = :id
干杯
Nik您不能使用HQL执行递归查询。如前所述,它甚至不是标准的SQL。您有两个选择:
- 编写特定于供应商的递归本机
- 进行多个查询。例如:
// obtain the first node using your query
while (currentNode.parent != null) {
Query q = //create the query
q.setParameter("id", currentNode.getParentId());
Node currentNode = (Node) q.getSingleResult();
nodes.add(currentNode); // this is the Set
}
我肯定会选择第二个选项。虽然不可能编写您要求的递归查询,但可以使用HQL急切地获取层次结构;这样做至少可以让您在内存中遍历这棵树,而不必访问每一级的数据库
select n from Node n
left join fetch n.Children
我知道这个问题很老,但由于它在另一个问题中被链接,我想对此进行更新,因为它提供了在JPA模型之上使用递归CTE的支持
Blaze Persistence是JPA之上的查询生成器,它支持JPA模型之上的许多高级DBMS功能。要对CTE或递归CTE进行建模(这是您在这里需要的),首先需要引入一个CTE实体,该实体对CTE的结果类型进行建模
@CTE
@Entity
public class NodeCTE {
@Id Integer id;
}
针对您的示例的查询可能如下所示
List<String> titles = criteriaBuilderFactory.create(entityManager, String.class)
.withRecursive(NodeCTE.class)
.from(Node.class, "n1")
.bind("id").select("n1.id")
.where("n1.id").eq(nodeId)
.unionAll()
.from(Node.class, "n2")
.innerJoinOn(NodeCTE.class, "cte")
.on("cte.id").eq("n2.parent.id")
.end()
.bind("id").select("n2.id")
.end()
.from(Node.class, "n")
.select("n.title")
.where("n.id").in()
.from(NodeCTE.class, "c")
.select("c.id")
.end()
.getResultList();
WITH RECURSIVE NodeCTE(id) AS (
SELECT n1.id
FROM Node n1
WHERE n1.parent_id = :id
UNION ALL
SELECT n2.id
FROM Node n2
INNER JOIN NodeCTE cte ON n2.parent_id = cte.id
)
SELECT n.title
FROM Node n
WHERE n.id IN (
SELECT c.id
FROM NodeCTE c
)
您可以在文档中找到关于递归CTE的更多信息:我知道SQL不是递归的,我假设HQL的设计就是为了克服这个限制。如果树不是太深或太复杂,我也会选择Bozho的第二个解决方案。但是如果你的树有十个“查询”深,或者你有很多节点,你想得到这个完整的标题,你可能会遇到很多查询和性能问题。根据您的情况,一种解决方法是在保存记录时将完整标题写入数据库,从而在检索时节省时间。这确实是我的问题,树可能很深,这就是为什么我希望Hibernate负责优化如何与数据库交互。我希望它知道智能解决方案,并可能导致数据库转换为能够处理此类问题的数据库。因此,我认为答案是:HQL没有递归,请使用其他优化策略。我要说的是“物化路径”。非常感谢您的帮助:-)实际上,有一种方法可以实现递归SQL,但是MySQL不支持它,Hibernate/JPA也不支持它。