-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: Many-to-many to a inherited object retrieves all objects...
PostPosted: Mon Mar 26, 2007 1:27 pm 
Beginner
Beginner

Joined: Thu Sep 01, 2005 7:43 am
Posts: 31
Location: León (Spain)
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?

_________________
Please rate...

Expert on Hibernate errors... I've had them all... :P


Top
 Profile  
 
 Post subject: I encountered the same problem
PostPosted: Tue Aug 28, 2007 7:32 am 
Newbie

Joined: Tue Aug 28, 2007 7:27 am
Posts: 7
Is there a workaround for this ?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 29, 2007 10:56 am 
Newbie

Joined: Tue Aug 28, 2007 7:27 am
Posts: 7
We tried out the SingleTable inheritance with a ManyToMany


@Entity
@Table(name="SHB_PRINCIPAL")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE",discriminatorType=DiscriminatorType.INTEGER)
@Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL)
public class Principal implements Serializable {
....



@Entity
@DiscriminatorValue(PrincipalType.USER_NR)
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ApplicationUser extends Principal {

private static final long serialVersionUID = 1L;

@ManyToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},
targetEntity=Role.class)
@JoinTable(name="SHB_PRINCIPAL_TO_PRINCIPAL",
joinColumns=@JoinColumn(name="FROM_PRINCIPAL_ID"),
inverseJoinColumns=@JoinColumn(name="TO_PRINCIPAL_ID"))
private Set<Role> roles;

@ManyToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},
targetEntity=ApplicationGroup.class)
@JoinTable(name="SHB_PRINCIPAL_TO_PRINCIPAL",
joinColumns=@JoinColumn(name="FROM_PRINCIPAL_ID"),
inverseJoinColumns=@JoinColumn(name="TO_PRINCIPAL_ID"))
private Set<ApplicationGroup> groups;



@Entity
@DiscriminatorValue(PrincipalType.GROUP_NR)
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ApplicationGroup extends Principal {

private static final long serialVersionUID = 1L;

@ManyToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
@JoinTable(name="SHB_PRINCIPAL_TO_PRINCIPAL",
joinColumns=@JoinColumn(name="TO_PRINCIPAL_ID"),
inverseJoinColumns=@JoinColumn(name="FROM_PRINCIPAL_ID"))
private Set<ApplicationUser> users;

public ApplicationGroup() {
super();
this.type = PrincipalType.GROUP;
}

public Set<ApplicationUser> getUsers() {
return users;
}
public void setUsers(Set<ApplicationUser> users) {
this.users = users;
}
}


@Entity
@Table(name="SHB_PRINCIPAL_TO_PRINCIPAL")
@Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL)
public class PrincipalPrincipal implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID")
private Integer id;

@ManyToOne
@JoinColumn(name="FROM_PRINCIPAL_ID")
private Principal fromPrincipal;

@Required
@ManyToOne
@JoinColumn(name="TO_PRINCIPAL_ID")
private Principal toPrincipal;

public PrincipalPrincipal() {
super();
}

public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}

public Principal getFromPrincipal() {
return fromPrincipal;
}

public void setFromPrincipal(Principal fromPrincipal) {
this.fromPrincipal = fromPrincipal;
}

public Principal getToPrincipal() {
return toPrincipal;
}

public void setToPrincipal(Principal toPrincipal) {
this.toPrincipal = toPrincipal;
}
}




But in the groups and the roles of the user, hibernate returns all principals, not only the users or groups. In the query it's clear that the descriminator is NOT used.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 29, 2007 3:15 pm 
Beginner
Beginner

Joined: Mon Aug 27, 2007 8:10 am
Posts: 37
dirk wrote:
But in the groups and the roles of the user, hibernate returns all principals, not only the users or groups. In the query it's clear that the descriminator is NOT used.


May you please clarify how do you expect Hibernate to use the column descriminator in the query?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 31, 2007 12:23 pm 
Newbie

Joined: Tue Aug 28, 2007 7:27 am
Posts: 7
In the ApplicationUser (subclass of Principal), there are 2 many-to-many relations 1 to ApplicationGroups(subclass of Principal) and 1 to Roles(subclass of Principal)
After adding some ApplicationGroups and Roles to an ApplicationUser, it should be possible to retrieve the ApplicationGroups and Roles separately. This is currently not the case because when asking for the ApplicationGroups of an ApplicationUser Hibernate will return all Principals (base class !!!)
This is because the discriminator is not used. Hibernate could easily know the real type because this is java 5 code with generics. So the types (ApplicationGroup and Role) are available all the time.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 31, 2007 2:41 pm 
Beginner
Beginner

Joined: Mon Aug 27, 2007 8:10 am
Posts: 37
dirk wrote:
In the ApplicationUser (subclass of Principal), there are 2 many-to-many relations 1 to ApplicationGroups(subclass of Principal) and 1 to Roles(subclass of Principal)
After adding some ApplicationGroups and Roles to an ApplicationUser, it should be possible to retrieve the ApplicationGroups and Roles separately. This is currently not the case because when asking for the ApplicationGroups of an ApplicationUser Hibernate will return all Principals (base class !!!)
This is because the discriminator is not used. Hibernate could easily know the real type because this is java 5 code with generics. So the types (ApplicationGroup and Role) are available all the time.


Can you add discriminator column to the join columns?


Top
 Profile  
 
 Post subject: There is a unit test available that simulates the problem
PostPosted: Wed Jan 09, 2008 11:19 am 
Newbie

Joined: Tue Aug 28, 2007 7:27 am
Posts: 7
http://opensource.atlassian.com/project ... e/HHH-2883


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.