enlait
enlait

Reputation: 616

Hibernate criteria - get a list of associated entities, not the parent ones

I've got two entities with unidirectional @OneToMany mapping:

@Entity
@Table(name = "table1")
public class A {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer pk;

    String name;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "a_pk", nullable = false)
    @Where(clause =  "is_deleted = 0")
    List<B> children;
}

@Entity
@Table(name = "table2")
public class B {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer pk;

    String content;

    @Column(name = "is_deleted",nullable=false)
    @NotNull
    boolean deleted = false;
}

I want to obtain a list of all B entities, which are children of A entities matching a restriction.

Criteria c = session.createCriteria(A.class)
    .add(Restriction.like("name", "Test%"))
    .createAlias("children","b");
???

And this is where I'm stuck: c.list() will return me a list of A objects. I don't care about A, I want B. How can I do it with Hibernate criteria/projections? If it matters, I use Hibernate 4.2.12

In this simplified case it would make sense to just fetch eagerly; in the real case there's a chain of four OneToMany unidirectional associations, and I want to get all (or better yet, SOME) children all the way down the tree knowing the root id; but I don't want to load all the intermediate stuff (it's not needed, and even if join-fetching four tables would work it's plain gross). Also, simply getting the root and following down the lazy associations is a clear example of N+1 problem escalated.

As a side question, does Hibernate criteria satisfy entity/property @Where restrictions?

Upvotes: 2

Views: 4025

Answers (2)

Rohit Girme
Rohit Girme

Reputation: 89

You can use projection to get list of "b". Like this :

Criteria c = session.createCriteria(A.class)
    .add(Restriction.like("name", "Test%"))
    .createAlias("children","b").setProjection(Projections.property("b"));

after this when you try to get results using c.list() it will return a list of B. I hope this helps!!

Upvotes: 2

enlait
enlait

Reputation: 616

So, yeah, I went with using HQL in the end. Nothing special.

List<B> bList = session.createQuery(
        "select b from A as a join a.children as b where a.name like 'Test%'"
        ).list();

Upvotes: 0

Related Questions