2

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

Nan
  • 63
  • 1
  • 9

1 Answers1

0

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.

v.ladynev
  • 19,275
  • 8
  • 46
  • 67
  • It's working well, but it's strange that hibernate don't propose this solution. Is there a reason? – Nan Nov 15 '17 at 10:26
  • Do you have a slution for @OneToMany collection ? I don't want to use the getter in lazy mode, it's so ugly... I want to do only one query to get my data – Nan Nov 16 '17 at 08:32
  • @Nan You can try it yourself. Maybe it will work. And you can use `criteria.setFetchMode()` to fetch a collection. – v.ladynev Nov 16 '17 at 10:18
  • Ok, but I just want to select some fields of my collection. I'm trying to do it with the transformer you gave me. I will push the solution when I will make it. – Nan Nov 16 '17 at 14:34
  • @Nan I think it is impossible. You can check entity graphs https://www.thoughts-on-java.org/jpa-21-entity-graph-part-1-named-entity/ – v.ladynev Nov 16 '17 at 17:55
  • You're right it's impossible because Hibernate loader treats row by row. So the transformer is called on each row, but not on the full result. – Nan Nov 17 '17 at 16:05
  • @Nan Thank you. Probably transformer can accumulate rows to the list, if Hibernate passes the name of the association. – v.ladynev Nov 17 '17 at 16:14