HHH-7377 - NullPointerException in conjunction with natural IDs after Session.clear()
(cherry picked from commit 785e2d869e
)
This commit is contained in:
parent
502542d2b6
commit
e5f0db2455
|
@ -2092,6 +2092,15 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
public void cleanupFromSynchronizations() {
|
||||
naturalIdXrefDelegate.unStashInvalidNaturalIdReferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEviction(Object object, EntityPersister persister, Serializable identifier) {
|
||||
naturalIdXrefDelegate.removeNaturalIdCrossReference(
|
||||
persister,
|
||||
identifier,
|
||||
findCachedNaturalId( persister, identifier )
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
|
|
|
@ -830,6 +830,15 @@ public interface PersistenceContext {
|
|||
* of old values as no longer valid.
|
||||
*/
|
||||
public void cleanupFromSynchronizations();
|
||||
|
||||
/**
|
||||
* Called on {@link org.hibernate.Session#evict} to give a chance to clean up natural-id cross refs.
|
||||
*
|
||||
* @param object The entity instance.
|
||||
* @param persister The entity persister
|
||||
* @param identifier The entity identifier
|
||||
*/
|
||||
public void handleEviction(Object object, EntityPersister persister, Serializable identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -80,7 +80,7 @@ public class DefaultEvictEventListener implements EvictEventListener {
|
|||
if ( !li.isUninitialized() ) {
|
||||
final Object entity = persistenceContext.removeEntity( key );
|
||||
if ( entity != null ) {
|
||||
EntityEntry e = event.getSession().getPersistenceContext().removeEntry( entity );
|
||||
EntityEntry e = persistenceContext.removeEntry( entity );
|
||||
doEvict( entity, key, e.getPersister(), event.getSession() );
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +106,10 @@ public class DefaultEvictEventListener implements EvictEventListener {
|
|||
LOG.tracev( "Evicting {0}", MessageHelper.infoString( persister ) );
|
||||
}
|
||||
|
||||
if ( persister.hasNaturalIdentifier() ) {
|
||||
session.getPersistenceContext().getNaturalIdHelper().handleEviction( object, persister, key.getIdentifier() );
|
||||
}
|
||||
|
||||
// remove all collections for the entity from the session-level cache
|
||||
if ( persister.hasCollections() ) {
|
||||
new EvictVisitor( session ).process( object, persister );
|
||||
|
|
|
@ -2491,12 +2491,12 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
|
|||
// synchronization (this process) was disabled
|
||||
return;
|
||||
}
|
||||
if ( ! isTransactionInProgress() ) {
|
||||
// not in a transaction so skip synchronization
|
||||
if ( entityPersister.getEntityMetamodel().hasImmutableNaturalId() ) {
|
||||
// only mutable natural-ids need this processing
|
||||
return;
|
||||
}
|
||||
if ( entityPersister.getEntityMetamodel().hasImmutableNaturalId() ) {
|
||||
// only mutable natural-ids need this processing
|
||||
if ( ! isTransactionInProgress() ) {
|
||||
// not in a transaction so skip synchronization
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2505,6 +2505,16 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
|
|||
final Object entity = getPersistenceContext().getEntity( entityKey );
|
||||
final EntityEntry entry = getPersistenceContext().getEntry( entity );
|
||||
|
||||
if ( entry == null ) {
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debug(
|
||||
"Cached natural-id/pk resolution linked to null EntityEntry in persistence context : "
|
||||
+ MessageHelper.infoString( entityPersister, pk, getFactory() )
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !entry.requiresDirtyCheck( entity ) ) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -472,4 +472,58 @@ public class MutableNaturalIdTest extends BaseCoreFunctionalTestCase {
|
|||
t.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClear() {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
User u = new User( "steve", "hb", "superSecret" );
|
||||
s.persist( u );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
u = (User) session.byNaturalId( User.class )
|
||||
.using( "name", "steve" )
|
||||
.using( "org", "hb" )
|
||||
.load();
|
||||
assertNotNull( u );
|
||||
s.clear();
|
||||
u = (User) session.byNaturalId( User.class )
|
||||
.using( "name", "steve" )
|
||||
.using( "org", "hb" )
|
||||
.load();
|
||||
assertNotNull( u );
|
||||
s.delete( u );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEviction() {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
User u = new User( "steve", "hb", "superSecret" );
|
||||
s.persist( u );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
u = (User) session.byNaturalId( User.class )
|
||||
.using( "name", "steve" )
|
||||
.using( "org", "hb" )
|
||||
.load();
|
||||
assertNotNull( u );
|
||||
s.evict( u );
|
||||
u = (User) session.byNaturalId( User.class )
|
||||
.using( "name", "steve" )
|
||||
.using( "org", "hb" )
|
||||
.load();
|
||||
assertNotNull( u );
|
||||
s.delete( u );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue