简体   繁体   中英

Hibernate 4: HQL and Inheritance - fetching collections and javassist

I'm having this scenario: parent class Person, children classes: Individual and Enterprise. I'm mapping this classes with joined-subclass strategy like this:

<hibernate-mapping>
  <class catalog="test" name="test.Person" table="Persons">
    <id name="id" type="int">
      <column name="IdPerson"/>
      <generator class="increment"/>
    </id>

    <set inverse="true" name="addresses">
      <key>
        <column name="IdPerson" not-null="true"/>
      </key>
      <one-to-many class="test.Address"/>
    </set>

    <set inverse="true" name="phones">
      <key>
        <column name="IdPerson" not-null="true"/>
      </key>
      <one-to-many class="test.Phone"/>
    </set>

    <joined-subclass name="test.Individual" table="Individuals">
      <key column="IdPerson"/>

      <property name="nameIndividual" type="string">
        <column length="30" name="Name" not-null="true"/>
      </property>
    ...
    </joined-subclass>

    <joined-subclass name="test.Enterprise" table="Enterprises">
      <key column="IdPerson"/>

      <property name="nameEnterprise" type="string">
        <column length="30" name="Name" not-null="true"/>
      </property>
    ...
    </joined-subclass>

  </class>

  <class catalog="test" name="test.Address" table="Addresses">

    <composite-id class="test.AddressId" name="id">
      <key-many-to-one name="person" class="test.Person">
        <column name="IdPerson" not-null="true"/>
      </key-many-to-one>
      <key-property name="id" type="int">
        <column name="IdAddress"/>
      </key-property>
    </composite-id>

    <many-to-one name="person" class="test.Person" fetch="select" insert="false" update="false">
      <column name="IdPerson" not-null="true"/>
    </many-to-one>
    ...    
  </class>

  <class catalog="test" name="test.Phone" table="Phones">

    <composite-id class="test.PhoneId" name="id">
      <key-many-to-one name="person" class="test.Person">
        <column name="IdPerson" not-null="true"/>
      </key-many-to-one>
      <key-property name="id" type="int">
        <column name="IdPhone"/>
      </key-property>
    </composite-id>

    <many-to-one name="person" class="test.Person" fetch="select" insert="false" update="false">
      <column name="IdPerson" not-null="true"/>
    </many-to-one>
    ...
  </class>

</hibernate-mapping>

When I use this simple HQL to load a list of Persons:

List result = session.createQuery("from Person as en").list();

hibernate resolves the polymorphism ok, and I get a list of Individuals and Enterprises objects.

But when I include the Addresses and Phones:

List result = session.createQuery("from Person as en left join fetch en.addresses left join fetch en.phones").list();

hibernate returns a list of Person_$$_javassist_5 objects with no access to the specific properties of Indivual and Enterprise classes.

Is this the expected behaviour? How could I solve this?

Thanks in advance.

EDITED:

I have included the Address and Phone classes mapping, its id's are composite and it seems to be the reason for the javassist proxy generated by hibernate, but why the proxy doesn't resolve the polymorphism correctly? even when hibernate gets all data from database.

My JSF page throws an javax.el.PropertyNotFoundException error: The class 'test.Person_$$_javassist_5' does not have the property 'nameIndividual'.

I tried similar example ie one class having two joined-subclasses and the parent class has one-to-many association.

Like in your example, I retrieved parent class record without using fetch and then "left join fetch".

Both the time it retrieved one-to-many association correctly.

When I used fetch mode, the resulting list contained duplicate records.

eg in one-to-many association, one record has 4 records in related table, then resulting list contained same object 4 times. For other record, if the related has 2 records, then resulting list contained same object 2 times.

But this is expected as per Hibernate docs :- http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html

"The fetch construct cannot be used in queries called using iterate() (though scroll() can be used). Fetch should be used together with setMaxResults() or setFirstResult(), as these operations are based on the result rows which usually contain duplicates for eager collection fetching, hence, the number of rows is not what you would expect. Fetch should also not be used together with impromptu with condition. It is possible to create a cartesian product by join fetching more than one collection in a query, so take care in this case. Join fetching multiple collection roles can produce unexpected results for bag mappings, so user discretion is advised when formulating queries in this case. Finally, note that full join fetch and right join fetch are not meaningful."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM