Hi, I'm getting the following exception, where Hibernate is trying to load a subclass of one type, but the object being returned is another type. The type that Hibernate is expecting is actually wrong. ID 2 really is supposed to be OpenEndedQuestion. So the type it's loading is fine... I dunno why Hibernate is complaining for.
Here is the exception:
Code:
org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException: Object with id: 2 was not of the specified subclass: jobprep.domain.finite.FiniteQuestion (loaded object was of wrong class class jobprep.domain.openended.OpenEndedQuestion); nested exception is org.hibernate.WrongClassException: Object with id: 2 was not of the specified subclass: jobprep.domain.finite.FiniteQuestion (loaded object was of wrong class class jobprep.domain.openended.OpenEndedQuestion)
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:663)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:424)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.get(HibernateTemplate.java:525)
at org.springframework.orm.hibernate3.HibernateTemplate.get(HibernateTemplate.java:519)
at jobprep.dao.ActiveModuleDaoImpl.find(ActiveModuleDaoImpl.java:34)
at jobprep.service.StudentServiceTests.assertActiveModuleContainsAmountOfActiveQuestions(StudentServiceTests.java:173)
at jobprep.service.StudentServiceTests.testEntireModuleToCompleteWithUser(StudentServiceTests.java:140)
at jobprep.service.StudentServiceTests.testEntireModuleToComplete(StudentServiceTests.java:120)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.springframework.test.context.junit4.SpringTestMethod.invoke(SpringTestMethod.java:160)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTestMethod(SpringMethodRoadie.java:233)
at org.springframework.test.context.junit4.SpringMethodRoadie$RunBeforesThenTestThenAfters.run(SpringMethodRoadie.java:333)
at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:217)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:197)
at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:143)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:160)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:97)
at com.intellij.rt.junit4.Junit4TestMethodAdapter.run(Junit4TestMethodAdapter.java:62)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
Here are two parts of the mapping where this could be the issue:
Code:
<class name="jobprep.domain.Question" table="question" abstract="true">
<id name="id" column="question_id" type="long">
<generator class="sequence">
<param name="sequence">question_id_sequence</param>
</generator>
</id>
<discriminator column="type" type="string"/>
<many-to-one name="task" class="jobprep.domain.Task" column="task_id" not-null="true" />
<property name="text" column="text"/>
<property name="ordering" column="ordering"/>
<property name="successMessage" column="success_message"/>
<bag name="activeQuestions" inverse="true" cascade="all-delete-orphan" lazy="true">
<key column="question_id" not-null="true"/>
<one-to-many class="jobprep.domain.ActiveQuestion"/>
</bag>
<subclass name="jobprep.domain.finite.FiniteQuestion" discriminator-value="FINITE">
<bag name="expectedAnswers" inverse="true" cascade="all-delete-orphan" order-by="text asc" lazy="false">
<key column="question_id" not-null="true"/>
<one-to-many class="jobprep.domain.finite.QuestionKeyword" />
</bag>
<bag name="hints" inverse="true" cascade="all-delete-orphan" order-by="attempts_needed asc" lazy="false">
<key column="question_id" not-null="true"/>
<one-to-many class="jobprep.domain.Hint"/>
</bag>
<property name="engineType" column="engine_type"/>
<property name="minimumNumberOfKeywords" column="minimum_number_of_keywords"/>
</subclass>
<subclass name="jobprep.domain.openended.OpenEndedQuestion" discriminator-value="OPEN-ENDED">
<bag name="keywords" inverse="true" cascade="all-delete-orphan" order-by="text asc" lazy="false">
<key column="question_id" not-null="true"/>
<one-to-many class="jobprep.domain.finite.QuestionKeyword" />
</bag>
<property name="minimumNumberOfWords" column="minimum_number_of_words"/>
<property name="minimumNumberOfWordsForFirstAttempt" column="minimum_number_of_words_for_first_attempt"/>
<property name="minimumNumberOfSentences" column="minimum_number_of_sentences"/>
<property name="minimumNumberOfKeywords" column="minimum_number_of_keywords"/>
</subclass>
<subclass name="jobprep.domain.category.CategoryBasedQuestion" discriminator-value="CATEGORY-BASED">
<bag name="categories" inverse="true" cascade="all-delete-orphan" order-by="name asc" lazy="false">
<key column="question_id" not-null="true"/>
<one-to-many class="jobprep.domain.category.Category"/>
</bag>
</subclass>
</class>
and this one:
Code:
<class name="jobprep.domain.ActiveQuestion" table="active_question">
<id name="id" column="active_question_id" type="long">
<generator class="sequence">
<param name="sequence">active_question_id_sequence</param>
</generator>
</id>
<many-to-one name="activeTask" class="jobprep.domain.ActiveTask" column="active_task_id"
not-null="true" cascade="all" />
<component name="results" class="jobprep.domain.QuestionResults">
<bag name="results" inverse="true" cascade="all-delete-orphan" lazy="false"
order-by="creation_date asc">
<key column="active_question_id" not-null="true"/>
<one-to-many class="jobprep.domain.QuestionResult"/>
</bag>
</component>
<property name="isAnswered" column="is_answered"/>
<property name="failedAttempts" column="failed_attempts"/>
<many-to-one name="question" class="jobprep.domain.Question" column="question_id"
not-null="true" cascade="none" />
<property name="creationDate" column="creation_date"/>
</class>
<class name="jobprep.domain.QuestionResult" table="question_result" abstract="true">
<id name="id" column="question_result_id" type="long">
<generator class="sequence">
<param name="sequence">question_result_id_sequence</param>
</generator>
</id>
<discriminator column="type" type="string"/>
<many-to-one name="activeQuestion" class="jobprep.domain.ActiveQuestion" column="active_question_id"
not-null="true" cascade="none" />
<property name="creationDate" column="creation_date"/>
<subclass name="jobprep.domain.finite.FiniteResult" discriminator-value="FINITE">
<many-to-one name="question" class="jobprep.domain.finite.FiniteQuestion" column="question_id"
not-null="true" cascade="all" />
<property name="suppliedAnswer" column="supplied_answer"/>
<bag name="answers" table="question_result_to_answer" inverse="true"
cascade="all" order-by="text asc" lazy="false">
<key column="question_result_id" not-null="true"/>
<many-to-many class="jobprep.domain.finite.QuestionKeyword" column="answer_id" />
</bag>
</subclass>
<subclass name="jobprep.domain.openended.OpenEndedResult" discriminator-value="OPEN-ENDED">
<many-to-one name="question" class="jobprep.domain.openended.OpenEndedQuestion" column="question_id"
not-null="true" cascade="all" />
<property name="suppliedAnswer" column="supplied_answer"/>
</subclass>
<subclass name="jobprep.domain.category.CategoryBasedResult" discriminator-value="CATEGORY-BASED">
<many-to-one name="question" class="jobprep.domain.category.CategoryBasedQuestion" column="question_id"
not-null="true" cascade="all" />
<bag name="answers" table="question_result_to_category_answer" inverse="true"
cascade="all" order-by="text asc" lazy="false">
<key column="question_result_id" not-null="true"/>
<many-to-many class="jobprep.domain.category.CategoryAnswer" column="category_answer_id" />
</bag>
</subclass>
</class>
Lastly, here are the database rows:
Code:
<question question_id="1" text="What is Sisko's first name?" task_id="1"
ordering="0" success_message="Correct!" type="FINITE" engine_type="SINGLE"
minimum_number_of_keywords="1" />
<question question_id="2" text="Why do you like Star Trek?" task_id="1"
ordering="1" success_message="You are a geek!" type="OPEN-ENDED"
minimum_number_of_keywords="0" minimum_number_of_words="4"
minimum_number_of_sentences="1" minimum_number_of_words_for_first_attempt="2"/>
<question question_id="3" text="Match the Star Trek items" task_id="1"
ordering="2" success_message="You are a trekkie!" type="CATEGORY-BASED"/>
<question question_id="4" text="Am I done yet?" task_id="2"
ordering="0" success_message="" type="OPEN-ENDED"
minimum_number_of_keywords="0" minimum_number_of_words="4"
minimum_number_of_sentences="1" minimum_number_of_words_for_first_attempt="2"/>
Clearly, id 2 is of type "OPEN-ENDED", so it doesn't make much sense why hibernate wants "FINITE" :( Hibernate is messed up.
This error happens when loading a totally different object... but when it's loading the object graph, something went wrong I guess? I dunno. I don't understand why this is failing.
Help?