Question

How is possible select top level parent node of child node in Hibernate, with HQL?

Example: I have object (Webpage) with ID:13 and I would like get her parent (in this example webpage with ID:6). Is it possible using HQL? I'm using PostgreSQL.

enter image description here

Model

@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
}**
Was it helpful?

Solution 2

Final solution:

@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 Query:

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

NOTE: :childrenNodeId must bind/replace of you children node ID. Value -1, represents initial value.

I hope thats help

OTHER TIPS

You can use with recursive get your result, for 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)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top