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)
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>