-->
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.  [ 5 posts ] 
Author Message
 Post subject: WrongClassException with one-to-one mapping and inheritance
PostPosted: Sat Feb 05, 2005 12:28 am 
Newbie

Joined: Fri Feb 04, 2005 11:39 pm
Posts: 13
Hello,
This problem is not specific to the new feature set of hibernate 3.0, but I am reporting this in this forum as I am using Hibernate 3.0

I have two tables Operations and Participants. From realtional point of view, Operations to particpants is one to many relationships, but participants can be of three types, Submitting Agency, Operation Contact and Other Agenceis. An operation can have exactly one submitting agency, zero or one operation contact and zero or more other agencies(enforced by business rules).

I am working on a proof of concept to convince management to use Hibernate instead of entity 2.x beans.

For now, I am trying to use one table per class hierarchy for Participants with Participant as the abstract base class and SubmittingAgency and OperationContact as its concretet subclasses. These subclasses do not have any addtional attributes or behaviours, but I am trying to model it this way just so that I can have two bidrectional (foregin key mapped) one-to-one relationships (each for submtting agency and operation contact).
I have read the book "Hibernate in action" and it mentions that we should be able to do this.

When I run the prgram, I get a WrongClassException while trying to load the OperationContact. None of the sql queries generated by Hibernate have discriminator type coulmn in the where caluse. Am I missing something in my mapping or code or could it be an unsupported feature or bug. Please refer to the mapping files, code snippets as per the given format:

Please note that Participants has Opn_ID as the foreign key column which is the primary key of Operations.

Hibernate version:hibernate-3.0_beta_1

Mapping documents:

(Relavant Sections)
Operation Class

.......
<one-to-one name="submittingAgency"
class="gov.ca.doj.sins.cev.model.SubmittingAgency"
property-ref="saToOperation"/>

<one-to-one name="operationContact"
class="gov.ca.doj.sins.cev.model.OperationContact"
property-ref="ocToOperation"/>
......

Participant, SubmittingAgency, OperationContact classes
.....
<class
name="gov.ca.doj.sins.cev.model.Participant"
table="PARTICIPANTS"
dynamic-update="true" lazy="false"
>

<id
name="id"
type="java.lang.String"
column="ID"
>
<generator class="gov.ca.doj.sins.cev.persistence.UniqueSequenceNumberFactory"/>
</id>

<discriminator
column="PARTICIPATION_TYPE_CODE"
type="string" force="true"/>
........

<subclass
name="gov.ca.doj.sins.cev.model.SubmittingAgency"
discriminator-value="SA" lazy="false">

<many-to-one name="saToOperation"
class="gov.ca.doj.sins.cev.model.Operation"
column="OPN_ID" insert="false" update="false"
cascade="all"
unique="true"/>


</subclass>

<subclass
name="gov.ca.doj.sins.cev.model.OperationContact"
discriminator-value="OC" lazy="false">

<many-to-one name="ocToOperation"
class="gov.ca.doj.sins.cev.model.Operation"
column="OPN_ID" insert="false" update="false"
cascade="all"
unique="true"/>
</subclass>

........

Code between sessionFactory.openSession() and session.close():

Service Layer
.....................
OperationDAO opnDAO = new OperationDAO();
List operations = opnDAO.getOperationsBySearchCriteria(searchParam);
HibernateUtil.closeSession();
return operations;


DAO constructor
....................
HibernateUtil.beginTransaction();


Dao
-----------
Session session = HibernateUtil.getSession();
Criteria operationCrit = session.createCriteria(Operation.class);
Criteria submittingAgencyCrit = session.createCriteria(SubmittingAgency.class);
if(searchParams.getBeginDate() != null)
{
operationCrit.add(Expression.ge("operationBeginDateTime", searchParams.getBeginDate()));
}

........

catch(HibernateException ex)
{
throw new InfrastructureException(ex);
}

Full stack trace of any exception that occurs:
org.hibernate.WrongClassException: Object with id: 0000004066500101 was not of the specified subclass: gov.ca.doj.sins.cev.model.OperationContact (loaded object was of wrong class) at org.hibernate.loader.Loader.instanceAlreadyLoaded(Loader.java:707) at org.hibernate.loader.Loader.getRow(Loader.java:661) at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:278) at org.hibernate.loader.Loader.doQuery(Loader.java:366) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:193) at org.hibernate.loader.Loader.loadEntity(Loader.java:1133) at org.hibernate.loader.EntityLoader.load(EntityLoader.java:111) at org.hibernate.loader.EntityLoader.loadByUniqueKey(EntityLoader.java:102) at org.hibernate.persister.BasicEntityPersister.loadByUniqueKey(BasicEntityPersister.java:1204) at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:278) at org.hibernate.type.EntityType.resolve(EntityType.java:226) at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:86) at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:426) at org.hibernate.loader.Loader.doQuery(Loader.java:388) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:193) at org.hibernate.loader.Loader.doList(Loader.java:1303) at org.hibernate.loader.Loader.list(Loader.java:1286) at org.hibernate.loader.CriteriaLoader.list(CriteriaLoader.java:167) at org.hibernate.impl.SessionImpl.find(SessionImpl.java:1564) at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:274) at gov.ca.doj.sins.cev.dao.OperationDAO.getOperationsBySearchCriteria(OperationDAO.java:107) at gov.ca.doj.sins.cev.service.CriticalEventService.retrieveOperations(CriticalEventService.java:34) at gov.ca.doj.sins.cev.ejb.CEVSessionFacadeBean.retrieveOperations(CEVSessionFacadeBean.java:178) at CEVSessionFacade_StatelessSessionBeanWrapper0.retrieveOperations(CEVSessionFacade_StatelessSessionBeanWrapper0.java:257) at gov.ca.doj.sins.cev.struts.action.RetrieveAction.processRetrieve(RetrieveAction.java:275) at gov.ca.doj.sins.cev.struts.action.RetrieveAction.execute(RetrieveAction.java:96) at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:480) at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274) at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1420) at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:520) at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at com.evermind.server.http.ResourceFilterChain.doFilter(ResourceFilterChain.java:65) at oracle.security.jazn.oc4j.JAZNFilter.doFilter(JAZNFilter.java:293) at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:611) at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:317) at com.evermind.server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:782) at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:270) at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:112) at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:192) at java.lang.Thread.run(Thread.java:534)

[b]Name and version of the database you are using:
oracle 9 i

[b]The generated SQL (show_sql=true):


The sql query to retrieve operation by search criteria
does a left outer join with Submitting Agency, but without
the descriminator column in the where close

The second sql query (looks klke immediate retrieve) queries Particpant
table to retrieve operation contact but without the discriminator column in the where clause.

Debug level Hibernate log excerpt:


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 05, 2005 7:44 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
I didn't really read properly, but what happens when you use <discriminator force="true"/>


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 05, 2005 3:54 pm 
Newbie

Joined: Fri Feb 04, 2005 11:39 pm
Posts: 13
Hi Gavin,
Thanks for your reply. Yes I did try with force="true" (as shown in the included xml mapping snippet for Participant). It does not seem to make a difference.

I even tried to give both many to one mappings different names (saToOperation for SubmittingAgency and ocToOperation for OperationContact and made them corresponding properties in the respective subclasses), but even this didn't seem to help.

Could you please help?
Regards
Anil


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 05, 2005 6:22 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Oh, sorry, these are one-to-ones, not one-to-manys. You need either:

* change the two one-to-one associations to be a single association to the superclass
* change the two many-to-one associations to map to different FK columns


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 06, 2005 1:13 am 
Newbie

Joined: Fri Feb 04, 2005 11:39 pm
Posts: 13
Hi Gavin,
Thanks again for your reply.

Option 1:I am not sure if it will fit my model If I change the two one to one associations (to respective subclasses) to one one-to-one association to the super class.

Actually, we are using Web-> session facade->service layer->DAO -> Hibernate architecture and I was trying to figure out if just using persistent POJOs for the web layer will be appropriate for our application.

That's why I was trying to map two one to one associations from Operation to Participant (one for SubmittingAgency and one for OperationContact). These are subclasses of Participant (with no addtional attribute/behaviour), but just used to signal the type of participant.
There is exactly one SubmttingAgency (participation_type_code='SA' and zero or one Operation contact participation_type_code='OC').

I want the web layer to say operation.getSubmittingAgency() and operation.getOperationContact() to render the relavant information.
Can I still do that if I change to one one-to-one association to the superclass?

Option 2: If I understand it correctly, you are advising me to define two columns (say opn1_id and opn_2id) in Participant having a foregin key constraint to the primary key (id) of Operation (assuming database will let me do that) and use these two columns to define the two one to one associations to the subclasses
[I'll have a hard time to convince my Schema Gurus to let me define two foreign keys to the same primary key just because Hibernate requires me to do that for the object model I want :-)].




This should fit my model. Please let me know if I understand your advice correctly.

I'll try these options on Monday.
Regards
Anil


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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.