Map hibernate projections result to java POJO mode

2019-04-10 22:04发布

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.

1条回答
贪生不怕死
2楼-- · 2019-04-10 22:51

Never mind, I've found the solution.

  1. First we need to create alias of the associated object like so

    Criteria criteria = sessionFactory.getCurrentSession().createCriteria("model.Person");
    criteria.createAlias("cars", "cars");
    
  2. 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"));
    
  3. 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"));
    
  4. Use the aggregate function

    projections.add(Projections.min("cars.year").as("minYear"));
    projections.add(Projections.max("cars.year").as("maxYear"));
    
  5. Set the projection

    criteria.setProjection(projections);
    
  6. Use result transformer AliasToBeanResultTransformer to map the result fields (as specified in step 2 & 4) to the POJO

    criteria.setResultTransformer(new AliasToBeanResultTransformer(Person.class));
    
  7. Get the result

    List<Person> results = (List<Person>) criteria.list();
    
查看更多
登录 后发表回答