Hibernate 3.0.5. I am doing a table-per-class hierarchy for a set of my classes. Everything seems to map fine, but if I have a collection of the base class type as a many-to-many set in another object the collection is pulled back as an arbitrary subclass type, not as the base class.
An example is that I have a hierarchy of media. Media is the base class and Video, Audio, and Image are the subclasses. I use a discriminator in the mapping:
Code:
<class name="Media" table="MEDIA" lazy="false">
...
<discriminator column="MEDIA_TYPE_CODE" type="string" force="true"/>
<!-- Video -->
<subclass name="Video" discriminator-value="VIDEO">
...
</subclass>
<!-- Image -->
<subclass name="Image" discriminator-value="IMAGE">
...
</subclass>
<!-- Audio -->
<subclass name="Audio" discriminator-value="AUDIO">
...
</subclass>
</class>
I map media as a many-to-many set in another object:
Code:
<class name="Library">
...
<set name="media"
inverse="false"
lazy="false"
cascade="all-delete-orphan"
table="MEDIA_LINK">
<key column="LIBRARY_ID"/>
<many-to-many class="Media" column="MEDIA_ID"/>
</set>
...
</class>
When Hibernate accesses the collection, it seems to get the first type in the collection then tries to cast the rest of the collection to that type.
For example, if I have a mix of Media subclasses in the collection [Image, Video, Video, Video, Audio] Hibernate will read the first row, then try to cast all subsequent rows to type Image, which results in:
Code:
org.hibernate.WrongClassException: Object with id: 1214 was not of the specified subclass: Image (loaded object was of wrong class)
at org.hibernate.loader.Loader.instanceAlreadyLoaded(Loader.java:890)
at org.hibernate.loader.Loader.getRow(Loader.java:846)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:305)
at org.hibernate.loader.Loader.doQuery(Loader.java:412)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:218)
at org.hibernate.loader.Loader.loadCollection(Loader.java:1434)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:99)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:488)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1430)
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:280)
at org.hibernate.engine.PersistenceContext.initializeNonLazyCollections(PersistenceContext.java:796)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:223)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1345)
at org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:116)
at org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:101)
at org.hibernate.persister.entity.BasicEntityPersister.load(BasicEntityPersister.java:2471)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:351)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:332)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:113)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:151)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:79)
at org.hibernate.impl.SessionImpl.load(SessionImpl.java:603)
at org.hibernate.impl.SessionImpl.load(SessionImpl.java:596)
at org.springframework.orm.hibernate3.HibernateTemplate$3.doInHibernate(HibernateTemplate.java:489)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:365)
at org.springframework.orm.hibernate3.HibernateTemplate.load(HibernateTemplate.java:483)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:335)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:181)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
at $Proxy7.findAssetById(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:427)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:378)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:546)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:89)
at org.testng.TestRunner.privateRun(TestRunner.java:620)
at org.testng.TestRunner.run(TestRunner.java:503)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:201)
at org.testng.SuiteRunner.run(SuiteRunner.java:128)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:99)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:138)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:86)
Am I doing something totally wrong?