使用HQL选择子节点的顶级节点

时间:2014-04-10 22:04:36

标签: sql hibernate postgresql hql hierarchical-data

如何在Hibernate中使用HQL选择子节点的顶级父节点?

示例: 我有ID:13的对象(网页),我想得到她的父母(在这个例子中ID为6的网页)。是否可以使用HQL?我正在使用PostgreSQL。

enter image description here

模型

@Entity
public class Webpage {

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name = "parent_id") 
    private Webpage parent;

    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Set<Webpage> childrens;

    // getter setter
}**

2 个答案:

答案 0 :(得分:0)

您可以使用递归获取结果,对于exp:

digoal=# create table tp(id int , childid int, info text);
CREATE TABLE
digoal=# insert into tp values (1,2,'test');
INSERT 0 1
digoal=# insert into tp values (1,3,'test');
INSERT 0 1
digoal=# insert into tp values (2,4,'test');
INSERT 0 1
digoal=# insert into tp values (4,5,'test');
INSERT 0 1
digoal=# insert into tp values (4,6,'test');
INSERT 0 1
digoal=# insert into tp values (6,7,'test');
INSERT 0 1
digoal=# insert into tp values (8,9,'test');
INSERT 0 1
digoal=# insert into tp values (8,10,'test');
INSERT 0 1
digoal=# insert into tp values (8,11,'test');
INSERT 0 1
digoal=# insert into tp values (11,13,'test');
INSERT 0 1
digoal=# insert into tp values (11,14,'test');
INSERT 0 1

digoal=# select * from tp order by id,childid;
 id | childid | info 
----+---------+------
  1 |       2 | test
  1 |       3 | test
  2 |       4 | test
  4 |       5 | test
  4 |       6 | test
  6 |       7 | test
  8 |       9 | test
  8 |      10 | test
  8 |      11 | test
 11 |      13 | test
 11 |      14 | test
(11 rows)


digoal=# with recursive t as (
  select id from tp where childid=7
union all
  select tmp.id from tp as tmp join t on (tmp.childid=t.id)
) select row_number() over() , * from t order by 1 desc limit 1;
 row_number | id 
------------+----
          4 |  1
(1 row)

答案 1 :(得分:0)

最终解决方案:

@Override
public Webpage getTopParentWebpage(final Webpage childrenNode) {
    Validate.notNull(childrenNode);
    StringBuilder sql = new StringBuilder();

    sql.append("with recursive tmp_webpage(id, parent) as ( ")
       .append("    values(-1::BIGINT, :childrenNodeId::BIGINT) ")
       .append(" union all ")
       .append("    select w.id, w.parent_id ")
       .append("    from tmp_webpage as tw, webpage as w ")
       .append("    where w.id = parent ")
       .append(" ) ")
       .append(" select * from webpage w where id = ( select t.id from tmp_webpage as t where t.parent is NULL ) ");    

    Query query = sessionFactory.getCurrentSession().createSQLQuery(sql.toString())
            .addEntity(Webpage.class)
            .setMaxResults(1)
            .setLong("childrenNodeId", childrenNode.getId());

    return (Webpage)query.uniqueResult();
}

SQL查询:

with recursive tmp_webpage(id, parent) as (
    values(-1::BIGINT, :childrenNodeId::BIGINT)
  union all
    select w.id, w.parent_id from tmp_webpage as tw, webpage as w
    where w.id = parent 
) 
select * from webpage where id = ( select t.id from tmp_webpage as t where t.parent is NULL ) ;

注意::childrenNodeId 必须绑定/替换您的子节点ID。值 -1 ,表示初始值。

我希望有帮助