简体   繁体   中英

Hibernate sort entities by property of children mapped as Map<String, Child>

Here is my model:

@Entity
@Table(name = "parent")
public class Parent {

    ...

    @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, cascade = { CascadeType.REMOVE}, mappedBy = "parent")
    @MapKeyColumn(name = "key")
    private Map<String, Child> children;

    ...

}

@Entity
@Table(name = "child")
public class Child {

    ...

    @Column(name = "key")
    private String key;

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

    @Column(name = "property")
    private String property;

    ...

}

That mapping is usefull and works on inserting, updating, deleting entites and selecting them.

Now I have to order Parent entites using their children property depending on map key, a something like order by parent.children[<particular key>].property asc clause(which I did not find in HQL). Also I have no idea how to achieve this using Criteria API. Any idea?

Only solution I have now is to select Children filtered by key and ordered by property and then fetch parents in Java code one by one which is not efficient even with "fetch parent" set.

The table created statements come out like this:

create table child (id bigint not null, key varchar(255), property varchar(255), parent_id bigint, primary key (id))
create table parent (id bigint not null, primary key (id))

with a constraint on parent_id to the parent table.

Working backwards, the sql seems pretty straight forward:

select p.* from parent p join child c on p.id = c.parent_id where c.key = 'c1' order by c.property asc;

And so the JPQL and Criteria query should also be straight forward:

List<Parent> po1 = em.createQuery("select p from Parent p join p.children c where c.key='c1' order by c.property asc", Parent.class).getResultList();
System.out.println(po1);

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Parent> cq = cb.createQuery(Parent.class);
Root<Parent> p = cq.from(Parent.class);
Join<Parent, Child> c = p.join("children");
cq.select(p).where(cb.equal(c.get("key"), "c1")).orderBy(cb.asc(c.get("property")));
List<Parent> po3 = em.createQuery(cq).getResultList();
System.out.println(po3);

Create a toString method for Parent:

public String toString() {
    return "Parent:"+id+":"+children;
}

and Child:

public String toString() {
    return "Child:"+id+":"+key+":"+property;
}

And that gives me the following output:

Hibernate: select parent0_.id as id1_1_ from parent parent0_ inner join child children1_ on parent0_.id=children1_.parent_id where children1_.key='c1' order by children1_.property asc
[Parent:4:{c1=Child:5:c1:0}, Parent:1:{c1=Child:2:c1:1}]
Hibernate: select parent0_.id as id1_1_ from parent parent0_ inner join child children1_ on parent0_.id=children1_.parent_id where children1_.key=? order by children1_.property asc
[Parent:4:{c1=Child:5:c1:0}, Parent:1:{c1=Child:2:c1:1}]

Which looks to me to be the parents ordered by the child property where the key is a certain value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM