HHH-11426 - NullPointerException in getPersistenceUnitUtil().getIdentifier() on detached enhanced entity

This commit is contained in:
barreiro 2017-01-26 14:55:24 +00:00 committed by Andrea Boriero
parent f2728836af
commit 35211ee5f3
3 changed files with 88 additions and 11 deletions

View File

@ -11,6 +11,7 @@ import javax.persistence.PersistenceUnitUtil;
import javax.persistence.spi.LoadState;
import org.hibernate.Hibernate;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
@ -66,12 +67,18 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
}
if ( entity instanceof HibernateProxy ) {
final HibernateProxy proxy = (HibernateProxy) entity;
return proxy.getHibernateLazyInitializer().getIdentifier();
return ((HibernateProxy) entity).getHibernateLazyInitializer().getIdentifier();
}
else if ( entity instanceof ManagedEntity ) {
final ManagedEntity enhancedEntity = (ManagedEntity) entity;
return enhancedEntity.$$_hibernate_getEntityEntry().getId();
EntityEntry entityEntry = ((ManagedEntity) entity).$$_hibernate_getEntityEntry();
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 {
log.debugf(
@ -79,13 +86,17 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
"(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"
);
final Class entityClass = Hibernate.getClass( 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 );
return getIdentifierFromPersister( 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 );
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.test.bytecode.enhancement;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.test.bytecode.enhancement.detached.DetachedGetIdentifierTestTask;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
@ -83,6 +84,12 @@ public class EnhancerTest extends BaseUnitTestCase {
EnhancerTestUtils.runEnhancerTestTask( DirtyTrackingTestTask.class );
}
@Test
@TestForIssue( jiraKey = "HHH-11426" )
public void testDetached() {
EnhancerTestUtils.runEnhancerTestTask( DetachedGetIdentifierTestTask.class );
}
@Test
public void testEviction() {
EnhancerTestUtils.runEnhancerTestTask( EvictionTestTask.class );

View File

@ -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;
}
}