Search code examples
javahibernatecriteriahibernate-criteria

Hibernate Criteria: projection with joined entity


I'm trying to create a query with Criteria, but I don't succeed to map data from a joined entity.

With this Criteria query the id of the Order entity is override with the id of the ShippingCondition entity :

final Criteria criteria = session.createCriteria(Order.class, "o")
    .createAlias("o.shippingCondition", "sc", JoinType.INNER_JOIN)
    .setProjection(Projections.projectionList()
        .add(Projections.property("o.id"), "id")
        .add(Projections.property("o.orderNum"), "orderNum")
        .add(Projections.property("o.notes"), "notes")
        .add(Projections.property("sc.id"), "id"))
    .add(Restrictions.eq("o.id", id))
    .setResultTransformer(Transformers.aliasToBean(Order.class));

return (Order) criteria.uniqueResult();

My entities :

@Table(name = "order", schema = "myschema")
public class Order {

    private Integer id;
    private String orderNum;
    private String notes;
    private ShippingCondition shippingCondition;
    ...
}

@Table(name = "shipping_condition", schema = "myschema")
public class ShippingCondition {

    private Integer id;
    private String shippingCondition;
    private Integer sorting;
    ...
}

I have tryed to replace .add(Projections.property("sc.id"), "id") by .add(Projections.property("sc.id"), "shippingCondition.id") but then I get a ClassCastException (java.lang.ClassCastException: entity.Order cannot be cast to java.util.Map)

Do you have any idea how I can do that ?

Thanks


Solution

  • Hibernate doesn't support nested projections. You will need to create DTO for that. You can extend DTO from Order class and add methods to set fields of ShippingCondition.

    class OrderDto extends Order {
    
      public OrderDto() {
          setShippingCondition(new ShippingCondition());
      }
    
      public void setShippingConditionId(Integer id) {
          getShippingCondition().setId(id);
      }
    
    }
    

    You can use a special nested transformer if you don't want to use DTO

    How to transform a flat result set using Hibernate

    Additional notes

    JPA doesn't support any transformers at all. And it is hard to implement such transformer by consistent way. For example, my transformer doesn't support child collections like @OneToMany, only single associations. Also, you can't use nested projections with HQL, because HQL doesn't support parent.child aliases.