Hibernate version: 3.2.2 GA
Mapping documents:
UsuarioFront has 4 or 5 sets of MasterTable objects mapped as unidirectional many-to-many's. A MasterTable stores info in a class-per-hierarchy inheritance model, using a String discriminator. For readability purposes, only one set is shown in the code.
Code:
@Entity
@PrimaryKeyJoinColumn(name="ID")
@Table(name= "USUARIO_FRONT")
public class UsuarioFront extends User implements Serializable {
private Set<Nacionalidad> nacionalidades;
@ManyToMany(
targetEntity=test.bean.model.mastertable.Nacionalidad.class
)
@JoinTable(
name="USUARIO_MASTERTABLE",
joinColumns={@JoinColumn(name="USUARIO_ID")},
inverseJoinColumns={@JoinColumn(name="MASTERTABLE_ID")}
)
public Set<Nacionalidad> getNacionalidades() {
return nacionalidades;
}
}
Code:
@Entity
@Table(name= "MASTERTABLE")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="TYPE",
discriminatorType=DiscriminatorType.STRING
)
public class MasterTable extends BaseObject implements Serializable {
public static final String TIPO = "TYPE";
}
@Entity
@DiscriminatorValue("Nacionalidad")
public class Nacionalidad extends MasterTable implements Serializable {
// nothing interesting here...
}
Code between sessionFactory.openSession() and session.close():Transaction control is delegated to Spring, and assigned in a per-service basis, so outside of the DAO, lazy loading is still active...
Code:
UsuarioFront uf = (UsuarioFront)usuarioFrontDAO.getObject(id, clazz);
Iterator it = uf.getNacionalidades().iterator();
while (it.hasNext()) {
MasterTable mt = (MasterTable)it.next();
mt.getId();
}
it = uf.getProfesiones().iterator();
while (it.hasNext()) {
MasterTable mt = (MasterTable)it.next();
mt.getId();
}
Full stack trace of any exception that occurs:
19:12:10,765 INFO [STDOUT] 19:12:10,765 WARN [RequestProcessor] Unhandled Exception thrown: class org.hibernate.WrongClassException
19:12:10,765 INFO [STDOUT] 19:12:10,765 ERROR [[action]] Servlet.service() for servlet action threw exception
org.hibernate.WrongClassException: Object with id: 37 was not of the specified subclass: test.bean.model.mastertable.Profesion (loaded object was of wrong class class test.bean.model.mastertable.Nacionalidad)
at org.hibernate.loader.Loader.instanceAlreadyLoaded(Loader.java:1234)
at org.hibernate.loader.Loader.getRow(Loader.java:1186)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:568)
at org.hibernate.loader.Loader.doQuery(Loader.java:689)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadCollection(Loader.java:1985)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:36)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:565)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1716)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:344)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
at test.service.UsuarioFrontServiceImpl.getObject(UsuarioFrontServiceImpl.java:75)
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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:281)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:187)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:154)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:176)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:176)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:210)
at $Proxy91.getObject(Unknown Source)
at test.webapp.action.PerfilAction.datosPersonales(PerfilAction.java:62)
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.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:270)
at org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:187)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:697)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.jboss.web.tomcat.tc5.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:156)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
at java.lang.Thread.run(Thread.java:595)
Name and version of the database you are using: Oracle 10
The generated SQL (show_sql=true):
select nacionalid0_.USUARIO_ID as USUARIO1_1_, nacionalid0_.MASTERTABLE_ID as MASTERTA2_1_, nacionalid1_.ID as ID6_0_, nacionalid1_.CONCEPTO as CONCEPTO6_0_ from UED_USUARIO_MASTERTABLE nacionalid0_, UED_MASTERTABLE nacionalid1_ where nacionalid0_.MASTERTABLE_ID=nacionalid1_.ID(+) and nacionalid0_.USUARIO_ID=?
The first thing that comes to mind is that the SQL isn't including the discriminator, and the sets are being filled with all the MasterTables found in the DB. One solution is to use diferent link tables for every set, but it is desired to stay as only one... ¿Someone knows what is wrong? ¿or simply isn't it feasible?