HQL recursion, how do I do this?

前端 未结 3 1415
再見小時候
再見小時候 2020-12-03 14:20

I have a tree structure where each Node has a parent and a Set children. Each Node has a String title, and I want to make

3条回答
  •  星月不相逢
    2020-12-03 15:00

    I know this question is old, but as it was linked in a different question, I wanted to give an update on this, as Blaze-Persistence offers support for working with recursive CTEs on top of the JPA model.

    Blaze-Persistence is a query builder on top of JPA which supports many of the advanced DBMS features on top of the JPA model. To model CTEs or recursive CTEs, which is what you need here, you first need to introduce a CTE entity that models the result type of the CTE.

    @CTE
    @Entity
    public class NodeCTE {
      @Id Integer id;
    }
    

    A query for your example could look like the following

    List 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();
    

    This renders to SQL looking like the following

    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
    )
    

    You can find out more about recursive CTEs in the documentation: https://persistence.blazebit.com/documentation/core/manual/en_US/index.html#recursive-ctes

提交回复
热议问题