Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Complex Hibernate Projections

I want to ask, it is possible that I create query projections and criterion for more than one level deep? I have 2 model classes:

@Entity  
@Table(name = "person")  
public class Person implements Serializable {
    @Id
    @GeneratedValue
    private int personID;
    private double valueDouble;
    private int valueInt;
    private String name;
    @OneToOne(cascade = {CascadeType.ALL}, orphanRemoval = true)
    @JoinColumn(name="wifeId")
    private Wife wife;
       /*   
        *  Setter Getter    
        */
}


@Entity 
@Table(name = "wife")  
public class Wife implements Serializable {

    @Id
    @GeneratedValue     
    @Column(name="wifeId")
    private int id;
    @Column(name="name")
    private String name;
    @Column(name="age")
    private int age;            
    /*
     *  Setter Getter
     */       
}

My Criteria API :

ProjectionList projections = Projections.projectionList(); 
projections.add(Projections.property("this.personID"), "personID");
projections.add(Projections.property("this.wife"), "wife");
projections.add(Projections.property("this.wife.name"), "wife.name");

Criteria criteria = null; 
criteria = getHandlerSession().createCriteria(Person.class); 
criteria.createCriteria("wife", "wife", JoinType.LEFT.ordinal()); 
criterion = Restrictions.eq("wife.age", 19);  
criteria.add(criterion); 
criteria.setProjection(projections);
criteria.setResultTransformer(Transformers.aliasToBean(Person.class)); 
return criteria.list();

and I hope, I can query Person, with specified criteria for wife property, and specified return resultSet. so i used Projections for getting specified return resultSet

I want personID, name(Person), name(Wife) will returned. how API i must Use, i more prefer use Hibernate Criteria API.

This time, I used code above for getting my expected result, but it will throw Exception with error message : Exception in thread "main" org.hibernate.QueryException: could not resolve property: wife.name of: maladzan.model.Person, and whether my Restrictions.eq("wife.age", 19); is correct for getting person which has wife with 19 as her age value ?

Thanks

like image 968
Fauzi Achmad Avatar asked Aug 24 '12 08:08

Fauzi Achmad


People also ask

What is a hibernate projection?

To put it simple, Hibernate Projections are used in order to query only a subset of the attributes of an entity or group of entities you're querying with Criteria. You can also use Projections to specify distinct clauses and aggregate functions like max , sum and so on.

How do you fetch a one to many DTO projection with JPA and Hibernate?

Fetching a one-to-many DTO projection with JPA and Hibernate. The postDTOMap is where we are going to store all PostDTO entities that, in the end, will be returned by the query execution. The reason we are using the postDTOMap is that the parent rows are duplicated in the SQL query result set for each child record.

What is CriteriaBuilder in Java?

public interface CriteriaBuilder. Used to construct criteria queries, compound selections, expressions, predicates, orderings. Note that Predicate is used instead of Expression<Boolean> in this API in order to work around the fact that Java generics are not compatible with varags. Since: Java Persistence 2.0.

Which Hibernate object can be used as data transfer object?

DTO projections using Tuple and native SQL queries This one is available from Hibernate 5.2.


1 Answers

AFAIK it is not possible to project more than one level deep with aliastobean transformer. Your options are

  • create a flattened Data Transfer Object (DTO)
  • fill the resulting Person in memory yourself
  • implement your own resulttransformer (similar to option 2)

option 1 looks like this:

Criteria criteria = getHandlerSession().createCriteria(Person.class)
    .createAlias("wife", "wife", JoinType.LEFT.ordinal())
    .add(Restrictions.eq("wife.age", 19)); 
    .setProjection(Projections.projectionList()
        .add(Projections.property("personID"), "personID")
        .add(Projections.property("name"), "personName")
        .add(Projections.property("wife.name"), "wifeName"));
    .setResultTransformer(Transformers.aliasToBean(PersonWifeDto.class));

return criteria.list();
like image 70
Firo Avatar answered Oct 02 '22 05:10

Firo