Reputation: 7295
I've been using spring and hibernate for this past few weeks and I've always been learning something new there.
Right now I've got a problem that I want to solve with Projections in Hibernate.
Suppose there is a model Person
and that model has many Car
. The following are how the class definitions roughly gonna look like:
public class Person implements java.io.Serializable {
private Integer id;
private String name;
private List<Car> cars;
private Integer minYear; // Transient
private Integer maxYear; // Transient
}
public class Car implements java.io.Serializable {
private Integer id;
private Integer year;
}
The problem here is I want to get the minYear
(maxYear
) of each Person
to be filled by the earliest year (latest year) of the cars
they have.
Later I found a solution to use Projections
but I stumbled upon org.hibernate.QueryException: could not resolve property: minYear of: model.Person
and here is the code of the db operation:
Criteria criteria = sessionFactory.getCurrentSession().createCriteria("model.Person");
criteria.add(create(personInstance));
criteria.createAlias("minYear", "minYear");
criteria.setProjection(Projections.min("cars.year").as("minYear"));
Is there anyway to store the aggregation value in transient method using Projections
because I just want to avoid using plain SQL and HQL as much as possible.
Upvotes: 4
Views: 8132
Reputation: 7295
Never mind, I've found the solution.
First we need to create alias of the associated object like so
Criteria criteria = sessionFactory.getCurrentSession().createCriteria("model.Person");
criteria.createAlias("cars", "cars");
Select the needed using Hibernate Projections
ProjectionList projections = Projections.projectionList();
projections.add(Projections.property("id").as("id"));
projections.add(Projections.property("name").as("name"));
projections.add(Projections.property("cars").as("cars"));
Group the result based on the root entity (in this case using its id, Person.id), this is needed especially when used with aggregation to group the aggregation
projections.add(Projections.groupProperty("id"));
Use the aggregate function
projections.add(Projections.min("cars.year").as("minYear"));
projections.add(Projections.max("cars.year").as("maxYear"));
Set the projection
criteria.setProjection(projections);
Use result transformer AliasToBeanResultTransformer
to map the result fields (as specified in step 2 & 4) to the POJO
criteria.setResultTransformer(new AliasToBeanResultTransformer(Person.class));
Get the result
List<Person> results = (List<Person>) criteria.list();
Upvotes: 6