DefaultLoadEventListener#onLoad throws exception when DelayedPostInsertIdentifier is set as an entity id

Description

DefaultLoadEventListener#onLoad has this code:

if ( idClass != null && ! idClass.isInstance( event.getEntityId() ) ) {
throw new TypeMismatchException(
"Provided id of the wrong type. Expected: " + idClass + ", got " + event.getEntityId().getClass());
}

However, EntityIdentityInsertAction has this in it's constructor:

delayedEntityKey = isDelayed ? generateDelayedEntityKey() : null;

and method:

private synchronized EntityKey generateDelayedEntityKey() {
if ( !isDelayed ) {
throw new AssertionFailure( "cannot request delayed entity-key for non-delayed post-insert-id generation" );
}
return new EntityKey( new DelayedPostInsertIdentifier(), getPersister(), getSession().getEntityMode() );
}

In case an insert is tried outside of an existing transaction users may run into this problem (like I did).

I don't know what the best fix is. The easiest fix would be:

Index: /Users/eelcohillenius/Documents/workspace/hibernate3/src/org/hibernate/event/def/DefaultLoadEventListener.java
===================================================================
— /Users/eelcohillenius/Documents/workspace/hibernate3/src/org/hibernate/event/def/DefaultLoadEventListener.java (revision 11098)
+++ /Users/eelcohillenius/Documents/workspace/hibernate3/src/org/hibernate/event/def/DefaultLoadEventListener.java (working copy)
@@ -5,6 +5,7 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.NonUniqueObjectException;
@@ -10,7 +11,7 @@
import org.hibernate.NonUniqueObjectException;
import org.hibernate.PersistentObjectException;
import org.hibernate.TypeMismatchException;
-import org.hibernate.EntityMode;
+import org.hibernate.action.DelayedPostInsertIdentifier;
import org.hibernate.cache.CacheConcurrencyStrategy;
import org.hibernate.cache.CacheKey;
import org.hibernate.cache.entry.CacheEntry;
@@ -82,7 +83,7 @@
}
else {
Class idClass = persister.getIdentifierType().getReturnedClass();
- if ( idClass != null && ! idClass.isInstance( event.getEntityId() ) ) {
+ if ( idClass != null && ! (idClass.isInstance( event.getEntityId() ) || event.getEntityId() instanceof DelayedPostInsertIdentifier )) {
throw new TypeMismatchException(
"Provided id of the wrong type. Expected: " + idClass + ", got " + event.getEntityId().getClass()
);

but that would look like a quick hack to me.

Activity

Brett MeyerJuly 8, 2014 at 3:11 PM

Bulk rejecting stale issues. If this is still a legitimate issue on ORM 4, feel free to comment and attach a test case. I'll address responses case-by-case. Thanks!

Brett MeyerApril 7, 2014 at 5:48 PM

In an effort to clean up, in bulk, tickets that are most likely out of date, we're transitioning all ORM 3 tickets to an "Awaiting Test Case" state. Please see http://in.relation.to/Bloggers/HibernateORMJIRAPoliciesAndCleanUpTactics for more information.

If this is still a legitimate bug in ORM 4, please provide either a test case that reproduces it or enough detail (entities, mappings, snippets, etc.) to show that it still fails on 4. If nothing is received within 3 months or so, we'll be automatically closing them.

Thank you!

Dave CopelandMay 9, 2008 at 12:04 AM

My comment re: bug with foreign keys is not true (solvable by nullable=false in annotations), however the entitymanager workaround is still required to avoid this bug.

Dave CopelandMay 8, 2008 at 11:42 PM

I have experienced this problem running outside of an EJB container (running in Tomcat). The solution was to run inside a transaction, vi EntityManager.getTransaction(). Well, more of a workaround. Keep in mind that there's another bug where child entities are inserted with null foreign keys so your database has to allow null on all foreign keys.

Eelco HilleniusJanuary 25, 2007 at 3:12 AM

As a side note, EntityIdentityInsertAction can be improved. There is no reason why generateDelayedEntityKey should be synchronized and the isDelayed delayed test can be removed as that method is private is only called from the constructor (and isDelayed is final).

Rejected

Details

Assignee

Reporter

Components

Affects versions

Priority

Created January 25, 2007 at 3:06 AM
Updated July 8, 2014 at 3:11 PM
Resolved July 8, 2014 at 3:11 PM