1

I have two simple mapings:

<class name="org.testing.Person" table="PERSON">
        <id name="personId" type="long" column="PERSON_ID">
            <generator class="native"/>
        </id>
        <property name="personName" type="string" not-null="true" column="PERSON_NAME"/>
        <many-to-one name="personAddress" class="org.testing.Address" column="PERSON_ADDRESS"    not-null="true" cascade="all" unique="true"/>
</class>

and

<class name="org.testing.Address" table="ADDRESS">
    <id name="addressId" type="long" column="ADDRESS_ID">
        <generator class="native" />
    </id>
    <property name="street" column="ADDRESS_STREET" type="string" />
    <property name="city" column="ADDRESS_CITY" type="string" />
    <property name="state" column="ADDRESS_STATE" type="string" />
</class>

I try to get property of the person address like this:

session.createCriteria(Person.class)
                    .add(Restrictions.eq("personName", "Frodo"))
                    .createAlias("personAddress", "pa")
                    .setProjection(Projections.property("pa.street"))
                    .list();

and it works. Than like this:

session.createCriteria(Person.class)
                    .add(Restrictions.eq("personName", "Frodo"))
                    .createCriteria("personAddress")
                    .setProjection(Projections.property("street"))
                    .list();

and it throws: org.hibernate.QueryException: could not resolve property: street of: org.testing.Person. I assume both should give the same result. Where I am wrong? Thanks in advance!

catdog
  • 87
  • 2
  • 3
  • 9
  • Why are you using **createCriteria("personAddress")** in the second query? – ManuPK Jan 04 '12 at 08:07
  • I am using it because there is a property named **personAddress** in **Person** class and it is one end of the association to the **Address** class – catdog Jan 04 '12 at 08:16

2 Answers2

9

hibernate 3.3.2;

let us see code source :

 public Criteria createAlias(String associationPath, String alias, int joinType) {
    new Subcriteria( this, associationPath, alias, joinType );
    return this;
}


public Criteria createCriteria(String associationPath, int joinType) {
    return new Subcriteria( this, associationPath, joinType );
}

createCriteria return sub Criteria ,so all the operation is on sub Criteria ; but createAlias is return the criteria who create sub Criteria ;

example 1. Ad manyToone adgroup ; all of them have " name "properties

     Criteria criteria1    = s.createCriteria(Ad.class, "ad").add(Restrictions.eq("ad.id", Long.valueOf(343909))) ;
     Criteria criteria2    =  criteria1.createCriteria("adGroup")
                    .setProjection(Projections.property("name"))
         List list  = criteria2.list();


    List list = s.createCriteria(Ad.class, "ad").add(Restrictions.eq("ad.id", Long.valueOf(343909)))
                    .createAlias("adGroup", "adGroup")
                    .setProjection(Projections.property("name"))
                    .list();

let us say the name in adgroup is " aaaa " the name in ad is "bbbb" in first statement , "name" value of result is from adGroup entity = " aaaa ". in second statement , "name" value of result is from Ad entity "bbbb" .

ps1: if there is no "name" properties in adgroup entity ,but in ad entity, first statement will throw Exception: org.hibernate.QueryException: could not resolve property: name of: AdGroup ; but if u change to " .setProjection(Projections.property("ad.name")) ",it will be fine returning the value of ad's name

ps2 :first statement call list() by criteria2 ,but hibernate will process from the root criteria = criteria1 ; so the final sql will contain " where ad.id =343909 " from criteria1 ;

example 2.

enter image description here

teacher oneToMany student student oneToMany student

  List list1 = s.createCriteria(Teacher.class, "teacher").add(Restrictions.eq("teacher.id", Long.valueOf(343909)))
                    .createCriteria("students").createCriteria("books")
                    .list();



 List list2 = s.createCriteria(Teacher.class, "teacher").add(Restrictions.eq("teacher.id", Long.valueOf(343909)))
                    .createAlias("students").createCriteria("books").setProjection(Projections.property("name"))
                    .list();

second statement will throw Exception: org.hibernate.QueryException: could not resolve property: books of: Teacher; because books is a property of student that is difference between createCriteria and createAlias ;

phil
  • 620
  • 7
  • 12
9

.setProjection(Projections.property("street")) always operates on the root criteria. to project joined items you have to use the first version you posted.

Firo
  • 30,626
  • 4
  • 55
  • 94