[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-5038) Hibernate's collections pulls out incorrect subclasses when attributes among sub-classes are shared

Ken Egervari (JIRA) noreply at atlassian.com
Thu Mar 25 00:46:31 EDT 2010


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-5038?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=35948#action_35948 ] 

Ken Egervari commented on HHH-5038:
-----------------------------------

Basically, the solution is this.

If the collection is ever a subclass, the sql needs to guard it by using the discremeter value as part of the generated sql. Otherwise, it pulls the Teachers and Directors... and then it'll throw the exception because it is only supposed to be Teachers.

> Hibernate's collections pulls out incorrect subclasses when attributes among sub-classes are shared
> ---------------------------------------------------------------------------------------------------
>
>                 Key: HHH-5038
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5038
>             Project: Hibernate Core
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 3.3.2
>            Reporter: Ken Egervari
>            Priority: Critical
>
> Here's my forum thread.
> https://forum.hibernate.org/viewtopic.php?f=1&t=1003481&p=2427675#p2427675
> I think there's a probable bug in Hibernate when it comes to one-to-many relationships concerning subclasses that share the same properties.
> I am trying to model 3 beans - EducationFacility, Director and Teacher.
> Director and Teacher extend from UserAccount
> EducationFacility contains 1 director
> EducationFacility contains multiple teachers
> Director and Teacher have a link back to EducationFacility.
> The bug is when Hibernate tries to pull out educationFacility.teachers, it also pulls out the Director as well, because they both have a link to EducationFacility. Hibernate is not properly guarding the "teachers" collection by filtering out Directors. Here is the exception:
> {code}
> org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException: Object with id: 9 was not of the specified subclass: jobprep.domain.user.Teacher (loaded object was of wrong class class jobprep.domain.user.Director); nested exception is org.hibernate.WrongClassException: Object with id: 9 was not of the specified subclass: jobprep.domain.user.Teacher (loaded object was of wrong class class jobprep.domain.user.Director)
>    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:666)
>    at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
>    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
>    at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
>    at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:837)
>    at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:833)
> {code}
> The mapping is as follows:
> {code}
>     <class name="jobprep.domain.educationfacility.EducationFacility" table="education_facility">
>         <id name="id" column="education_facility_id" type="long">
>            <generator class="native" />
>         </id>
>         ....
>         <many-to-one name="director" class="jobprep.domain.user.Director"
>                      column="director_id" cascade="all" />
>         <bag name="teachers" inverse="true" cascade="all-delete-orphan" lazy="true" order-by="username asc">
>             <key column="education_facility_id" />
>             <one-to-many class="jobprep.domain.user.Teacher" />
>         </bag>
>         ....
>     </class>
>     <class name="jobprep.domain.user.UserAccount" table="user_account" abstract="true">
>         <id name="id" column="user_account_id" type="long">
>             <generator class="native" />
>         </id>
>         <discriminator column="user_type" type="string"/>
>         ....
>         <subclass name="jobprep.domain.user.Teacher" discriminator-value="ROLE_TEACHER">
>             <many-to-one name="educationFacility" class="jobprep.domain.educationfacility.EducationFacility"
>                          column="education_facility_id" not-null="false"/>
>             <bag name="students" inverse="true" cascade="all-delete-orphan"
>                  lazy="true">
>                 <key column="teacher_id" />
>                 <one-to-many class="jobprep.domain.student.Student"/>
>             </bag>
>         </subclass>
>         <subclass name="jobprep.domain.user.Director" discriminator-value="ROLE_DIRECTOR">
>             <many-to-one name="educationFacility" class="jobprep.domain.educationfacility.EducationFacility"
>                          column="education_facility_id" not-null="false"/>
>         </subclass>
>         ....
>     </class>
> {code}
> This code actually fixes it:
> {code}
>         ...
>         <subclass name="jobprep.domain.user.Director" discriminator-value="ROLE_DIRECTOR">
>             <many-to-one name="educationFacility" class="jobprep.domain.educationfacility.EducationFacility"
>                          column="owning_education_facility_id" not-null="false"/>
>         </subclass>
>         ...
> {code}
> This works because hibernate's SQL probably pulls out all the UserAccount's that have education_facility_id=?... and since I changed the column name, Hibernate will only pull out Teacher subclasses of UserAccount.
> Likewise, if I ever wanted to get all directors (if I ever changed it to be more than one), Hibernate's sql would only fetch the Directors.
> But this can't be right... this is so cludgy and bad. I'll work with it for now, but I think there is a problem with Hibernate that needs to be addressed here. When educationFacility.teachers is ever used, it shouldn't pull out Directors in the first place in the sql... but it is.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list