-->
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.  [ 4 posts ] 
Author Message
 Post subject: Serious error with mapped subclasses
PostPosted: Fri Aug 22, 2008 7:53 am 
Newbie

Joined: Wed Jul 30, 2008 1:54 pm
Posts: 11
I have an interesting mapping case that is causing me some very odd low-level errors. In this particular case, I'm working with a table that contains multiple objects and I can use a DiscriminatorColumn to differentiate.

To do this, I created a base class, gave it the DiscriminatorColumn annotation, and then extended it with my various types. I do this simply to have strong types and to use the discriminator column to help me narrow the 5000+ entries down into more manageable lists.

Here are the classes:

Code:
@Entity
@Table(name="WTTBLE")
@DiscriminatorColumn(name="PTBLE")
public abstract class MetaData
{
  @Id
  @Basic(fetch=FetchType.EAGER)
  @Column(name="PCODE", nullable=false, insertable=false, updatable=false)
  private String code = null;
 
  @Basic(fetch=FetchType.EAGER)
  @Column(name="DEF", nullable=false, insertable=false, updatable=false)
  private String value = null;
 
  ....
}

@Entity
@DiscriminatorValue(value = "015")
public class AddressType
extends MetaData
{
   // No fields here, they're all mapped in MetaData
}

@Entity
@DiscriminatorValue(value = "016")
public class CustomerType
extends MetaData
{
   // No fields here, they're all mapped in MetaData
}


Now, this works great until they both have the same value for the "code" property. At that point, I get the following logging and exception:

Quote:
org.hibernate.impl.SessionImpl - initializing proxy: [com.wiley.permissions.domain.persistence.wintouch.metadata.AddressType#A]
....
org.hibernate.event.def.DefaultLoadEventListener - load request found matching entity in context, but the matched entity was of an inconsistent return type; returning null
....
javax.persistence.EntityNotFoundException: Unable to find test.AddressType with id A
at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:107)
at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:79)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:68)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:150)
at test.AddressType$$EnhancerByCGLIB$$16d4c983.getValue(<generated>)


After some serious research, I found that org.hibernate.engine.StatefulPersistenceContext is returning the wrong object from it's getEntity method. It's returning a CustomerType object, which was added to the session's cache after the address type. On furthur examination, this seems to be because org.hibernate.engine.EntityKey.equals() is returning the same value for both objects. EntityKey's code for lines 95 -99 is:

Code:
   public boolean equals(Object other) {
      EntityKey otherKey = (EntityKey) other;
      return otherKey.rootEntityName.equals(this.rootEntityName) &&
         identifierType.isEqual(otherKey.identifier, this.identifier, entityMode, factory);
   }


Examination of the values of EntityKey for my objects show that rootEntityName for both objects is test.MetaData. That means that this method is going to return true. That, in turn, means that StatefulPersistenceContext's entitiesByKey HashMap is going to return the first one that equals the one passed into the get() method.

I'm not sure if this is a bug or not, but it seems to be somewhat odd behavior. It's entirely possible there's a better way to map these classes.

I'm open to any suggestions anyone may have.

---------------------------------------------
For the record, I'm using:

Hibernate Core: 3.2.6.ga
Hibernate EntityManager: 3.3.2.ga
Hibernate Annotations: 3.3.1.ga


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 25, 2008 5:18 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

Quote:
Now, this works great until they both have the same value for the "code" property.


What do you mean? Do you have one instance of AddressType and CustomerType with the same value for code? Given that code is the id column that would of course be wrong.

--Hardy


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 25, 2008 5:17 pm 
Newbie

Joined: Wed Jul 30, 2008 1:54 pm
Posts: 11
Well, wrong or not, it's the data I have to deal with in this legacy system.

As I understand Single Table Inheritence, I should be able to do this. The discriminator column should keep the various inherited entities distinct. So AddressType and CustomerType would be very different entities, so having the same ID shouldn't matter. The problem seems to be, that at least for caching purposes, org.hibernate.engine.StatefulPersistenceContext , uses EntityKey as the key in it's hashmaps. That's fine, but EntityKey uses the rootEntityName, which in this case would be MetaData, instead of the entityName, which would be AddressType or CustomerType. That means when AddressType is loaded and put in the cache, it's overwritten when CustomerType is loaded and put in the cache if CustomerType has the same ID.

I've done a lot of furthur research on this. I built my own version of 3.2.6.ga and debugged around until I found where things go wrong. I've described the problem a little more in JIRA under this bug: http://opensource.atlassian.com/project ... e/HHH-3445

I've even submitted a small patch to EntityKey that fixes this problem. I've been using my patched version for about 4 days now with fairly extensive use and have had no problems.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 27, 2008 5:06 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

per default the discriminator column is not part of the primary key. The described error is for this reason expected.

Here is a potential solution Steve suggested. You could try using a composite id mapping (combining 'code' and discriminator) and further mapping the discriminator property as 'immutable' (insert=false/update=false). But that is not a supported/tested setup.

--Hardy


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