Skip to content

Commit

Permalink
HHH-11426 - NullPointerException in getPersistenceUnitUtil().getIdent…
Browse files Browse the repository at this point in the history
…ifier() on detached enhanced entity
  • Loading branch information
barreiro authored and dreab8 committed Feb 15, 2017
1 parent f272883 commit 35211ee
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 11 deletions.
Expand Up @@ -11,6 +11,7 @@
import javax.persistence.spi.LoadState; import javax.persistence.spi.LoadState;


import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.ManagedEntity; import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.internal.util.PersistenceUtilHelper; import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
Expand Down Expand Up @@ -66,26 +67,36 @@ public Object getIdentifier(Object entity) {
} }


if ( entity instanceof HibernateProxy ) { if ( entity instanceof HibernateProxy ) {
final HibernateProxy proxy = (HibernateProxy) entity; return ((HibernateProxy) entity).getHibernateLazyInitializer().getIdentifier();
return proxy.getHibernateLazyInitializer().getIdentifier();
} }
else if ( entity instanceof ManagedEntity ) { else if ( entity instanceof ManagedEntity ) {
final ManagedEntity enhancedEntity = (ManagedEntity) entity; EntityEntry entityEntry = ((ManagedEntity) entity).$$_hibernate_getEntityEntry();
return enhancedEntity.$$_hibernate_getEntityEntry().getId(); if ( entityEntry != null ) {
return entityEntry.getId();
}
else {
// HHH-11426 - best effort to deal with the case of detached entities
log.debug( "javax.persistence.PersistenceUnitUtil.getIdentifier may not be able to read identifier of a detached entity" );
return getIdentifierFromPersister( entity );
}
} }
else { else {
log.debugf( log.debugf(
"javax.persistence.PersistenceUnitUtil.getIdentifier is only intended to work with enhanced entities " + "javax.persistence.PersistenceUnitUtil.getIdentifier is only intended to work with enhanced entities " +
"(although Hibernate also adapts this support to its proxies); " + "(although Hibernate also adapts this support to its proxies); " +
"however the passed entity was not enhanced (nor a proxy).. may not be able to read identifier" "however the passed entity was not enhanced (nor a proxy).. may not be able to read identifier"
); );
final Class entityClass = Hibernate.getClass( entity ); return getIdentifierFromPersister( entity );
final EntityPersister persister = sessionFactory.getMetamodel().entityPersister( entityClass );
if ( persister == null ) {
throw new IllegalArgumentException( entityClass + " is not an entity" );
}
//TODO does that work for @IdClass?
return persister.getIdentifier( entity );
} }
} }

private Object getIdentifierFromPersister(Object entity) {
Class<?> entityClass = Hibernate.getClass( entity );
EntityPersister persister = sessionFactory.getMetamodel().entityPersister( entityClass );
if ( persister == null ) {
throw new IllegalArgumentException( entityClass.getName() + " is not an entity" );
}
return persister.getIdentifier( entity, null );
}

} }
Expand Up @@ -8,6 +8,7 @@


import org.hibernate.bytecode.enhance.spi.UnloadedClass; import org.hibernate.bytecode.enhance.spi.UnloadedClass;


import org.hibernate.test.bytecode.enhancement.detached.DetachedGetIdentifierTestTask;
import org.hibernate.testing.FailureExpected; import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
Expand Down Expand Up @@ -83,6 +84,12 @@ public void testDirty() {
EnhancerTestUtils.runEnhancerTestTask( DirtyTrackingTestTask.class ); EnhancerTestUtils.runEnhancerTestTask( DirtyTrackingTestTask.class );
} }


@Test
@TestForIssue( jiraKey = "HHH-11426" )
public void testDetached() {
EnhancerTestUtils.runEnhancerTestTask( DetachedGetIdentifierTestTask.class );
}

@Test @Test
public void testEviction() { public void testEviction() {
EnhancerTestUtils.runEnhancerTestTask( EvictionTestTask.class ); EnhancerTestUtils.runEnhancerTestTask( EvictionTestTask.class );
Expand Down
@@ -0,0 +1,59 @@
package org.hibernate.test.bytecode.enhancement.detached;

import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.junit.Assert;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
* @author Luis Barreiro
*/
public class DetachedGetIdentifierTestTask extends AbstractEnhancerTestTask {

public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{SimpleEntity.class};
}

public void prepare() {
Configuration cfg = new Configuration();
cfg.setProperty( Environment.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "false" );
super.prepare( cfg );
}

public void execute() {
EntityManager em = getFactory().createEntityManager();
em.getTransaction().begin();

SimpleEntity se = new SimpleEntity();
se.name = "test";
se = em.merge( se );

Assert.assertNotNull( getFactory().getPersistenceUnitUtil().getIdentifier( se ) );

em.getTransaction().commit();
em.close();

// Call as detached entity
Assert.assertNotNull( getFactory().getPersistenceUnitUtil().getIdentifier( se ) );
}

protected void cleanup() {
}

@Entity
public static class SimpleEntity {

@Id
@GeneratedValue
private Long id;

private String name;

}
}

0 comments on commit 35211ee

Please sign in to comment.