-->
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.  [ 12 posts ] 
Author Message
 Post subject: Wrong subclass returned by Session.get(Class c, Object key)
PostPosted: Thu Apr 28, 2005 1:57 pm 
Newbie

Joined: Tue Mar 08, 2005 12:24 pm
Posts: 9
Location: Boston
Hibernate version:
3.0.1

Mapping documents:
table-per-hierarchy mapping (three subclasses)

I (mistakenly) tried to load a class using another subclass's key, and got an instance back, of the wrong type.

E.g. I have classes X, Xa, Xb and Xc, where X is the superclass of the other three, I map them all to one table and perform

Xb xb = ...
Session s =...
Xa xa = s.get(Xa.getClass(), xb.getId());

and I get an Xa instance back holding xb's data. (The DB correctly stored the xb instance with the discriminator tag indicating it is an instance of Xb.)

If this is not a known issue, either bug it or let me know and I'll bug it.


Top
 Profile  
 
 Post subject: Re: Wrong subclass returned by Session.get(Class c, Object k
PostPosted: Thu Apr 28, 2005 2:38 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
damo9f wrote:
Hibernate version:
3.0.1

Mapping documents:
table-per-hierarchy mapping (three subclasses)

I (mistakenly) tried to load a class using another subclass's key, and got an instance back, of the wrong type.

E.g. I have classes X, Xa, Xb and Xc, where X is the superclass of the other three, I map them all to one table and perform

Xb xb = ...
Session s =...
Xa xa = s.get(Xa.getClass(), xb.getId());

and I get an Xa instance back holding xb's data. (The DB correctly stored the xb instance with the discriminator tag indicating it is an instance of Xb.)

If this is not a known issue, either bug it or let me know and I'll bug it.



Also using v3.0.1

Session.load(Class c, Object k) is behaving the same way.

In my case, Client and Partner both subclass Person and are declared with descrimiators and Person is defined with polymorphism="explicit"
Code:
 

  Long clientId = new Long(1);
  Object obj = null;
  obj = session.get(Partner.class,clientId);   // returns client data as a Partner object
  obj = session.load(Partner.class,clientId);  // returns client data as a Partner object
  obj = session.createCriteria(Partner.class)
                     .add(Restrictions.eq("personId",clientId))
                     .uniqueResult();         // Correctly returns null.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 28, 2005 3:58 pm 
Newbie

Joined: Thu Apr 28, 2005 3:01 pm
Posts: 6
Location: Phoenix
Did anybody figure this out ?. I am also having similar problem.

I have Xa and X Xa is the subclass of X. I am try to get Xa, by passing Xa.class Here if Xa does not exist,but X exist.I am getting an instance of X. insted of a WrongClassException.

_________________
Jayan Nair


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 28, 2005 4:24 pm 
Newbie

Joined: Tue Mar 08, 2005 12:24 pm
Posts: 9
Location: Boston
I should have mentioned that there is a workaround -- query using the superclass (abstract superclass is ok) and check that the object is what you really want. Querying using the abstract class correctly uses the discriminator to instantiate the proper class in our case.

Inefficient, but will work.

Code:
public Xb getMatchingXb(Object myKey) {
  AbstractSuperX x = s.get(AbstractSuperX.class, myKey);
  if (!(x instanceof Xb))
     return null; // no match because class is wrong
  else
     return x;
}


As always, adding isXb() isXa() etc. methods is cleaner.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 28, 2005 4:36 pm 
Newbie

Joined: Thu Apr 28, 2005 3:01 pm
Posts: 6
Location: Phoenix
Finding the subclass object with Superclass type works fine.

But if I am interested only in the subclass, I should be able to find it by
get(XSub.class, myKey). Here if a record exist for XSub, It should return the instance, otherwise, a null or exception.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 28, 2005 5:15 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
jayanr wrote:
Finding the subclass object with Superclass type works fine.

But if I am interested only in the subclass, I should be able to find it by
get(XSub.class, myKey). Here if a record exist for XSub, It should return the instance, otherwise, a null or exception.



I have opened the following JIRA issue:

http://opensource.atlassian.com/project ... se/HHH-416


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 29, 2005 8:53 am 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
pksiv wrote:
jayanr wrote:
Finding the subclass object with Superclass type works fine.

But if I am interested only in the subclass, I should be able to find it by
get(XSub.class, myKey). Here if a record exist for XSub, It should return the instance, otherwise, a null or exception.



I have opened the following JIRA issue:

http://opensource.atlassian.com/project ... se/HHH-416


As you will see if you monitor this issue in JIRA...

According to Gavin...
"This is not a bug and has been the behavior of every version of Hibernate ever. "

So I guess we'll have to live with this behavior.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 29, 2005 11:58 am 
Newbie

Joined: Thu Apr 28, 2005 3:01 pm
Posts: 6
Location: Phoenix
That means, If we use Hibernate to map an inheritance relation using table per hierarchy strategy , We should never use 'get' or 'load' methods with subclass type ?.

Consider the following situation:

Person inherits from Employee. I have a method terminate() in Employee class. I have a person Id and find the employee with that person Id and terminate him.(Finding the employee with person Id because this is a table per hierarchy mapping and the primary Key is person Id for both Person and Employee)

I would like to find an Employee by personId and call terminate().Instead of finding a Person , and check whether he is an employee then call terminate()


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 29, 2005 12:09 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
You are completely misunderstanding the contract of get/load.

The contract is:

* I have an id which is the id of an instance of Subclass.
* get me that instance

If you want some other contract, use a query!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 29, 2005 12:57 pm 
Newbie

Joined: Thu Apr 28, 2005 3:01 pm
Posts: 6
Location: Phoenix
But in a table per hirarchy mapping, both Subclass and superclass will have the same Id colum in database right ?.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 29, 2005 2:56 pm 
Newbie

Joined: Thu Apr 28, 2005 3:01 pm
Posts: 6
Location: Phoenix
I am sorry, I made a mistake in the previuos post.

"Consider the following situation:

Person inherits from Employee. " is wrong.

Employee inherits from Person..

I used find("select query by person Id")

public Employee findEmployeeByPersonId(Long persontId){
List employees = null;
employees = getHibernateTemplate().find("from Person per where per.personid = ?",new Object[] {persontId});
if(!employees .isEmpty())
return (Employee)members.get(0);
else
return null;
}

Here , if If I pass a personId who is not an Employee, I am getting Class cast exception which means Hibernate is creating the Correct class "Person".


Top
 Profile  
 
 Post subject:
PostPosted: Sun May 01, 2005 11:26 pm 
Regular
Regular

Joined: Mon Sep 20, 2004 8:42 am
Posts: 58
Location: Boston, US
I feel that Hibernate's behaviour here is not intuitive.

The use case is strange as it seems backward that one would have an id and then try looking up the wrong subclass, however I feel that Hibernate's behaviour of coercing the object into the wrong subclass when given an ID of a different subclass is not the expected behavior.

The discriminator mapping for each subclass has been specified in the mapping while so when looking up an on object using code like one one below, the first filter that should take place should be that of the discriminator value followed by the user specified id.

Code:
session.get(Partner.class,clientId);


Sanjiv


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