Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java HQL递归,我该怎么做?_Java_Hibernate_Orm_Recursion_Hql - Fatal编程技术网

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也不支持它。