-->
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.  [ 1 post ] 
Author Message
 Post subject: Bug with ManyToOne on UK field of parent w/composite id
PostPosted: Thu Jun 30, 2011 7:14 pm 
Newbie

Joined: Mon Oct 11, 2010 5:24 pm
Posts: 6
First off, yes I know this approach is not recommended. Until Hibernate supports get(), load(), second level cache, etc with natural-id this is my only option.

I have an entity with a composite @EmbeddedId used for the primary key, and a generated unique surrogate ID that I use for FK associations to prevent the child tables from needing all the fields of the composite key.

Basically looks like this:

Code:

@Embeddable
class ParentId {
  String name;
  Date effectiveDate;
}

class Parent {
  @EmbeddedId
  ParentId compositeId;

  @Column(name="generatedId", unique=true)
  String generatedId;

  @OneToMany(mappedBy="parent")
  Set<Child> children;
}

class Child {
  @ManyToOne
  @JoinColumn(name="parentId", referencedColumnName="generatedId")
  Parent parent;
}



Any time I try to lazy load or join the child collection in a criteria or HQL query, an IllegalArgumentException results because Hibernate establishes the owner (parent) object's key as itself rather than as an instance of it's composite key class.

The offending code looks to be this part of org.hibernate.type.CollectionType, which seems to ignore the possibility that that the owner object might have a composite embedded key:

Code:
   public Serializable getKeyOfOwner(Object owner, SessionImplementor session) {
      
      EntityEntry entityEntry = session.getPersistenceContext().getEntry( owner );
      if ( entityEntry == null ) return null; // This just handles a particular case of component
                             // projection, perhaps get rid of it and throw an exception
      
      if ( foreignKeyPropertyName == null ) {
         return entityEntry.getId();
      }
      else {
         // TODO: at the point where we are resolving collection references, we don't
         // know if the uk value has been resolved (depends if it was earlier or
         // later in the mapping document) - now, we could try and use e.getStatus()
         // to decide to semiResolve(), trouble is that initializeEntity() reuses
         // the same array for resolved and hydrated values
         Object id;
[b]         if ( entityEntry.getLoadedState() != null ) {
            id = entityEntry.getLoadedValue( foreignKeyPropertyName );
         }[/b]
         else {
            id = entityEntry.getPersister().getPropertyValue( owner, foreignKeyPropertyName, session.getEntityMode() );
         }

         // NOTE VERY HACKISH WORKAROUND!!
         // TODO: Fix this so it will work for non-POJO entity mode
         Type keyType = getPersister( session ).getKeyType();
         if ( !keyType.getReturnedClass().isInstance( id ) ) {
            id = (Serializable) keyType.semiResolve(
                  entityEntry.getLoadedValue( foreignKeyPropertyName ),
                  session,
                  owner
               );
         }

         return (Serializable) id;
      }
   }


Now that the key has been established as the actual entity and not the ID class, a trainwreck is impending when I eventually hit this piece of code in org.hibernate.engine.StatefulPersistenceContext:

Code:
   /**
    * Get the entity that owns this persistent collection
    */
   public Object getCollectionOwner(Serializable key, CollectionPersister collectionPersister) throws MappingException {
      return getEntity( new EntityKey( key, collectionPersister.getOwnerEntityPersister(), session.getEntityMode() ) );
   }


In the consructor for EntityKey Hibernate attempts to generate a hashcode for the key by invoking the getters of my composite ID class. Problem is that the actual target object is an instance of the entity class not the ID class. End result is an IllegalArgumentException due to the mismatched classes.

I would really appreciate either confirmation that this is a bug or advice on how I can map this association to avoid this issue.

Thanks


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

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.