Search code examples
javahibernatehibernate-criteria

Nested property path in Projections.property()


I have the following code:

Session session = (Session) em.getDelegate();
Criteria c = session.createCriteria(Term.class);
c.setProjection(
        Projections.projectionList()
                .add(Projections.property("id"))
                .add(Projections.property("qualifier"))
                .add(Projections.property("preferred"))
                .add(Projections.property("terminology.definition"))
);
c.list();

but Hibernate chokes on terminology.definition with an exception org.hibernate.QueryException: could not resolve property: terminology.definition of: net.*.Term

despite the fact that there is a property in Term:

@OneToOne(mappedBy = "term")
public Terminology getTerminology() { return terminology; }

and Terminology has a @Basic property named definition. I can fix it with an stupid-looking alias:

session.createCriteria(Term.class).createAlias("terminology", "terminology")

but it is undesirable.


Solution

  • This is pretty standard due to the way selects are being done.
    Terminology is mostly like brought in through a join on the SQL side, but in terms of the query, you have to define an alias in order to be able to access a joined table.

    In fact, if you look at the JavaDocs for Criteria class, there's even an example of it:

    You may navigate associations using createAlias() or createCriteria().

     List cats = session.createCriteria(Cat.class)
         .createCriteria("kittens")
             .add( Restrictions.like("name", "Iz%") )
         .list();
    
     List cats = session.createCriteria(Cat.class)
         .createAlias("kittens", "kit")
         .add( Restrictions.like("kit.name", "Iz%") )
         .list();
    

    You'll notice you can either use an alias and the . notation, or you can use createCriteria with a straight property name.

    However, this example is for the where clause. Not 100% how it would play out for the projections (i.e., if you can have subcriteria with projections). I'd just stick to the alias approach you already have.