UmYeah
UmYeah

Reputation: 820

Hibernate query not returning full object

I have a list of items. Each item has set of categories. I want to grab all the items of a specific category. This part is simple. The part I am having problems with is getting my query to return the item with all of its categories, not just the one I am filtering on.

session.createCriteria(Item.class)
        .createAlias("categories","category")
        .add(Restrictions.eq("category.name",categoryFilter))

The above code returns the item but only with the category I am filtering on. Is there anyway to say filter the object on this restriction, but return the full object and not the filtered one? I have also tried writing this in HQL with the same results.

Upvotes: 2

Views: 3935

Answers (4)

Jeff Sheets
Jeff Sheets

Reputation: 1219

Another solution is to use an Exists Subquery so that FetchMode.JOIN will also work. (This uses DetachedCriteria but Criteria should be similar)

DetachedCriteria criteria = session.createCriteria(Item.class, "i");
criteria.setFetchMode("categories", FetchMode.JOIN);

DetachedCriteria catCriteria = DetachedCriteria.forClass(Category.class, "category");
catCriteria.add(Restrictions.eq("name", categoryFilter));
catCriteria.add(Restrictions.eqProperty("category.id", "i.categoryId"));
criteria.add(Subqueries.exists(catCriteria.setProjection(Projections.property("category.id"))));

Hope this helps someone else too since the docs are so hard to figure out. I also added a github gist with additional comments

Upvotes: 0

meriton
meriton

Reputation: 70584

If it is the bug I reported a while ago: My usual work-around is only fetch the id's of the matching items, and then select the items with their categories in a follow-up query:

List<Serializable> ids = session.createCriteria(Item.class)
    .createAlias("categories","category")
    .add(Restrictions.eq("category.name",categoryFilter))
    .setProjection(Projections.id())
    .list();

List<Items> items = session.createCriteria(Item.class)
    .add(Restrictions.in("id", ids)
    .createAlias("categories","category")
    .list();

Upvotes: 0

Don Roby
Don Roby

Reputation: 41145

It appears there really is some nasty interaction between FetchMode and createAlias, which looks like a bug to me.

There's some discussion of this at https://forums.hibernate.org/viewtopic.php?t=944439 with one of the developers saying emphatically that it's correct behavior and won't be fixed.

The discussion also contains potential workarounds though.

Try using a nested criteria instead of an alias:

session.createCriteria(Item.class)
   .createCriteria("categories")
       .add(Restrictions.eq("name",categoryFilter))

With the collection mapped as eager, this seems to work for me. Not sure of interaction with using FetchMode on the outer criteria.

Upvotes: 4

Don Roby
Don Roby

Reputation: 41145

This likely has not much to do with the use of the alias and restriction, but is just a result of default lazy fetching.

In your mapping of Item, you probably have categories set to fetch lazily, which is the default, and generally a good idea.

You can change this mapping to eager, but that's probably a bad idea.

To leave the default fetch lazy but make the specific criteria retrieve eagerly, you can set the fetch mode there, with something resembling

session.createCriteria(Item.class)
    .setFetchMode("categories", FetchMode.EAGER)
    .createAlias("categories","category")
    .add(Restrictions.eq("category.name",categoryFilter))

Upvotes: 0

Related Questions