HHH-16557 Testcase and bugfix proposal (revised by beikov)

This commit is contained in:
Guenther Demetz 2024-05-07 18:20:15 +02:00 committed by Christian Beikov
parent f44332ccfb
commit ece64c75fd
5 changed files with 60 additions and 6 deletions

View File

@ -174,7 +174,7 @@ public class EntityDeleteAction extends EntityAction {
final EntityKey key = entry.getEntityKey();
persistenceContext.removeEntityHolder( key );
removeCacheItem( ck );
persistenceContext.getNaturalIdResolutions().removeSharedResolution( id, naturalIdValues, persister );
persistenceContext.getNaturalIdResolutions().removeSharedResolution( id, naturalIdValues, persister, true);
postDelete();
}

View File

@ -433,6 +433,11 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
@Override
public void removeSharedResolution(Object id, Object naturalId, EntityMappingType entityDescriptor) {
removeSharedResolution( id, naturalId, entityDescriptor, false );
}
@Override
public void removeSharedResolution(Object id, Object naturalId, EntityMappingType entityDescriptor, boolean delayToAfterTransactionCompletion) {
final NaturalIdMapping naturalIdMapping = entityDescriptor.getNaturalIdMapping();
if ( naturalIdMapping == null ) {
// nothing to do
@ -453,7 +458,18 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
final EntityPersister persister = locatePersisterForKey( entityDescriptor.getEntityPersister() );
final Object naturalIdCacheKey = cacheAccess.generateCacheKey( naturalId, persister, session() );
cacheAccess.evict( naturalIdCacheKey );
if ( delayToAfterTransactionCompletion ) {
session().asEventSource().getActionQueue().registerProcess(
(success, session) -> {
if ( success ) {
cacheAccess.evict( naturalIdCacheKey );
}
}
);
}
else {
cacheAccess.evict( naturalIdCacheKey );
}
// if ( sessionCachedNaturalIdValues != null
// && !Arrays.equals( sessionCachedNaturalIdValues, deletedNaturalIdValues ) ) {
@ -479,7 +495,7 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
cacheResolution( pk, naturalIdValuesFromCurrentObjectState, persister );
stashInvalidNaturalIdReference( persister, cachedNaturalIdValues );
removeSharedResolution( pk, cachedNaturalIdValues, persister );
removeSharedResolution( pk, cachedNaturalIdValues, persister, false );
}
}

View File

@ -68,8 +68,12 @@ public interface NaturalIdResolutions {
/**
* Removes any cross-reference from the L2 cache
*/
void removeSharedResolution(Object id, Object naturalId, EntityMappingType entityDescriptor);
void removeSharedResolution(Object id, Object naturalId, EntityMappingType entityDescriptor, boolean delayToAfterTransactionCompletion);
default void removeSharedResolution(Object id, Object naturalId, EntityMappingType entityDescriptor) {
removeSharedResolution( id, naturalId, entityDescriptor, false );
}
/**
* Find the cached natural-id for the given identifier
*

View File

@ -4115,7 +4115,7 @@ public abstract class AbstractEntityPersister
? null
: naturalIdMapping.extractNaturalIdFromEntityState( entitySnapshot );
naturalIdResolutions.removeSharedResolution( id, naturalIdSnapshot, this );
naturalIdResolutions.removeSharedResolution( id, naturalIdSnapshot, this, false );
final Object naturalId = naturalIdMapping.extractNaturalIdFromEntity( entity );
naturalIdResolutions.manageLocalResolution( id, naturalId, this, CachedNaturalIdValueSource.UPDATE );
}

View File

@ -179,6 +179,40 @@ public abstract class CachedMutableNaturalIdTest {
}
);
}
@Test
@TestForIssue( jiraKey = "HHH-16557" )
public void testCreateDeleteRecreate(SessionFactoryScope scope) {
final Integer id = scope.fromTransaction(
(session) -> {
AllCached it = new AllCached( "it" );
session.persist(it);
session.remove(it);
// insert-remove might happen in an app driven by users GUI interactions
return it.getId();
}
);
// now recreate with same naturalId value
scope.inTransaction(
(session) -> {
AllCached it = new AllCached( "it" );
session.persist(it);
// resolving from first level cache
assertNotNull(session.bySimpleNaturalId( AllCached.class ).load( "it" ));
}
);
scope.inTransaction(
(session) -> {
// should resolve from second level cache
final AllCached shouldBeThere = session.bySimpleNaturalId( AllCached.class ).load( "it" );
assertNotNull( shouldBeThere );
assert(id.compareTo(shouldBeThere.getId()) != 0);
}
);
}
@Test
@JiraKey("HHH-16558")