Can I group by an a nested associated entity using Projections in hibernate?
If I have entities like:
@Entity
public class Person {
public String name;
@OneToMany
public Location location;
}
@Entity
public class Location {
public String address;
public String city;
public String state;
}
Say I want to count all of the people in each state. Should I be able to do something like this:
Criteria criteria = session.createCriteria(Person.class);
criteria.setProjection(Projections.projectionList().
add(Projections.groupProperty("location.state")).
add(Projections.开发者_如何学Ccount("name")));
List<Object[]> result = criteria.list();
I know that exact example won't work because I get an error saying, could not resolve property: location.state of of: Person
. Is there a way to do what I'm trying to do without resorting to HQL? (The real version of this query is quite dynamic, so the programmatic building of the criteria is very helpful.)
You can make the Location as an association for Person, and then group it there. For instance:
session.createCriteria(Person.class)
.add(Projections.count("name"))
.createCriteria(Location.class)
.add(Projections.groupProperty("state"))
Not tested, but should work :-)
First, I created a toy example above, so it's possible that the toy would have worked and even partenon's suggestion might have worked on the toy example. The documentation seems to indicate that either should, but it didn't work in my real scenario, which is too verbose to go into here.
The issue is that it couldn't find the location.state
property. What ultimately worked was to create aliases in the criteria explicitly:
criteria.createAlias("location", "location").createAlias("location.state", "state");
I was still not able to use the "state" alias, but "location.state" then worked for me, so creating the aliases somehow primed the query builder to be able to find it when it couldn't before. This all seems very hacky and inelegant, so I'm not proud of this solution, but it's what worked. Does this sound like a bug to anyone else?
For those curious, without going into the whole entity model, here is the actual criteria and projections that worked for me:
obsCriteria.createAlias("phenomenon", "phenomenon").createAlias(
"phenomenon.phenomenonGroup", "phenomenonGroup");
ProjectionList projection = Projections.projectionList()
.add(Projections.avg("value"))
.add(Projections.groupProperty("phenomenon.phenomenonGroup"));
obsCriteria.setProjection(projection);
精彩评论