[
http://opensource.atlassian.com/projects/hibernate/browse/HHH-5038?page=c...
]
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...
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....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira