HHH-7085 Use the in-flight state for naturalId caching

Pass the current state Object[] from the event into the SPC to use
for naturalId caching
This commit is contained in:
Eric Dalquist 2012-02-20 10:52:41 -06:00 committed by Steve Ebersole
parent b5ba7bef42
commit f1a54aeadf
4 changed files with 44 additions and 35 deletions

View File

@ -92,7 +92,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction {
throw new AssertionFailure( "possible nonthreadsafe access to session" );
}
entry.postInsert();
entry.postInsert( getState() );
if ( persister.hasInsertGeneratedProperties() ) {
persister.processInsertGeneratedProperties( id, instance, getState(), session );

View File

@ -1705,54 +1705,53 @@ public class StatefulPersistenceContext implements PersistenceContext {
// NATURAL ID RESOLUTION HANDLING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public void loadedStateInsertedNotification(EntityEntry entityEntry) {
public void loadedStateInsertedNotification(EntityEntry entityEntry, Object[] state) {
final EntityPersister persister = entityEntry.getPersister();
if ( !persister.hasNaturalIdentifier() ) {
// nothing to do
return;
}
final Object[] naturalIdValues = getNaturalIdValues( entityEntry, persister );
final Object[] naturalIdValues = getNaturalIdValues( state, persister );
// cache
cacheNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues, CachedNaturalIdValueSource.INSERT );
}
@Override
public void loadedStateUpdatedNotification(EntityEntry entityEntry) {
public void loadedStateUpdatedNotification(EntityEntry entityEntry, Object[] state) {
final EntityPersister persister = entityEntry.getPersister();
if ( !persister.hasNaturalIdentifier() ) {
// nothing to do
return;
}
final Object[] naturalIdValues = getNaturalIdValues( entityEntry, persister );
final Object[] naturalIdValues = getNaturalIdValues( state, persister );
// re-cache
cacheNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues, CachedNaturalIdValueSource.UPDATE );
}
@Override
public void loadedStateDeletedNotification(EntityEntry entityEntry) {
public void loadedStateDeletedNotification(EntityEntry entityEntry, Object[] deletedState) {
final EntityPersister persister = entityEntry.getPersister();
if ( !persister.hasNaturalIdentifier() ) {
// nothing to do
return;
}
final Object[] naturalIdValues = getNaturalIdValues( entityEntry, persister );
final Object[] naturalIdValues = getNaturalIdValues( deletedState, persister );
// evict from cache
evictNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues );
}
private Object[] getNaturalIdValues(EntityEntry entityEntry, EntityPersister persister) {
private Object[] getNaturalIdValues(Object[] state, EntityPersister persister) {
final int[] naturalIdPropertyIndexes = persister.getNaturalIdentifierProperties();
final Object[] naturalIdValues = new Object[naturalIdPropertyIndexes.length];
final Object[] loadedState = entityEntry.getLoadedState();
for ( int i = 0; i < naturalIdPropertyIndexes.length; i++ ) {
naturalIdValues[i] = loadedState[naturalIdPropertyIndexes[i]];
naturalIdValues[i] = state[naturalIdPropertyIndexes[i]];
}
return naturalIdValues;
@ -1990,27 +1989,38 @@ public class StatefulPersistenceContext implements PersistenceContext {
}
}
@Override
public void evictNaturalIdResolution(EntityPersister persister, final Serializable pk, Object[] naturalIdValues) {
private void evictNaturalIdResolution(EntityPersister persister, final Serializable pk, Object[] deletedNaturalIdValues) {
if ( !persister.hasNaturalIdentifier() ) {
throw new IllegalArgumentException( "Entity did not define a natural-id" );
throw new IllegalArgumentException( "Entity did not define a natrual-id" );
}
if ( persister.getNaturalIdentifierProperties().length != naturalIdValues.length ) {
if ( persister.getNaturalIdentifierProperties().length != deletedNaturalIdValues.length ) {
throw new IllegalArgumentException( "Mismatch between expected number of natural-id values and found." );
}
NaturalIdResolutionCache entityNaturalIdResolutionCache = naturalIdResolutionCacheMap.get( persister );
Object[] sessionCachedNaturalIdValues = null;
if ( entityNaturalIdResolutionCache != null ) {
final LocalNaturalIdCacheKey localNaturalIdCacheKey = new LocalNaturalIdCacheKey( persister,
naturalIdValues );
entityNaturalIdResolutionCache.pkToNaturalIdMap.remove( pk );
entityNaturalIdResolutionCache.naturalIdToPkMap.remove( localNaturalIdCacheKey );
final LocalNaturalIdCacheKey localNaturalIdCacheKey = entityNaturalIdResolutionCache.pkToNaturalIdMap
.remove( pk );
if ( localNaturalIdCacheKey != null ) {
entityNaturalIdResolutionCache.naturalIdToPkMap.remove( localNaturalIdCacheKey );
sessionCachedNaturalIdValues = localNaturalIdCacheKey.getValues();
}
}
if ( persister.hasNaturalIdCache() ) {
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
final NaturalIdCacheKey naturalIdCacheKey = new NaturalIdCacheKey( naturalIdValues, persister, session );
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister
.getNaturalIdCacheAccessStrategy();
final NaturalIdCacheKey naturalIdCacheKey = new NaturalIdCacheKey( deletedNaturalIdValues, persister,
session );
naturalIdCacheAccessStrategy.evict( naturalIdCacheKey );
if ( sessionCachedNaturalIdValues != null
&& !Arrays.equals( sessionCachedNaturalIdValues, deletedNaturalIdValues ) ) {
final NaturalIdCacheKey sessionNaturalIdCacheKey = new NaturalIdCacheKey( sessionCachedNaturalIdValues,
persister, session );
naturalIdCacheAccessStrategy.evict( sessionNaturalIdCacheKey );
}
}
}
}

View File

@ -241,7 +241,7 @@ public final class EntityEntry implements Serializable {
.getCustomEntityDirtinessStrategy()
.resetDirty( entity, getPersister(), (Session) persistenceContext.getSession() );
notifyLoadedStateUpdated();
notifyLoadedStateUpdated( updatedState );
}
/**
@ -253,17 +253,17 @@ public final class EntityEntry implements Serializable {
status = Status.GONE;
existsInDatabase = false;
notifyLoadedStateDeleted();
notifyLoadedStateDeleted( deletedState );
}
/**
* After actually inserting a row, record the fact that the instance exists on the
* database (needed for identity-column key generation)
*/
public void postInsert() {
public void postInsert(Object[] insertedState) {
existsInDatabase = true;
notifyLoadedStateInserted();
notifyLoadedStateInserted( insertedState );
}
public boolean isNullifiable(boolean earlyInsert, SessionImplementor session) {
@ -360,7 +360,7 @@ public final class EntityEntry implements Serializable {
}
setStatus( Status.MANAGED );
loadedState = getPersister().getPropertyValues( entity );
notifyLoadedStateUpdated();
notifyLoadedStateUpdated( loadedState );
}
}
@ -374,28 +374,28 @@ public final class EntityEntry implements Serializable {
return loadedWithLazyPropertiesUnfetched;
}
private void notifyLoadedStateUpdated() {
private void notifyLoadedStateUpdated(Object[] state) {
if ( persistenceContext == null ) {
throw new HibernateException( "PersistenceContext was null on attempt to update loaded state" );
}
persistenceContext.loadedStateUpdatedNotification( this );
persistenceContext.loadedStateUpdatedNotification( this, state );
}
private void notifyLoadedStateInserted() {
private void notifyLoadedStateInserted(Object[] state) {
if ( persistenceContext == null ) {
throw new HibernateException( "PersistenceContext was null on attempt to insert loaded state" );
}
persistenceContext.loadedStateInsertedNotification( this );
persistenceContext.loadedStateInsertedNotification( this, state );
}
private void notifyLoadedStateDeleted() {
private void notifyLoadedStateDeleted(Object[] deletedState) {
if ( persistenceContext == null ) {
throw new HibernateException( "PersistenceContext was null on attempt to delete loaded state" );
}
persistenceContext.loadedStateDeletedNotification( this );
persistenceContext.loadedStateDeletedNotification( this, deletedState );
}
/**

View File

@ -683,11 +683,11 @@ public interface PersistenceContext {
*/
public boolean wasInsertedDuringTransaction(EntityPersister persister, Serializable id);
public void loadedStateUpdatedNotification(EntityEntry entityEntry);
public void loadedStateUpdatedNotification(EntityEntry entityEntry, Object[] state);
public void loadedStateInsertedNotification(EntityEntry entityEntry);
public void loadedStateInsertedNotification(EntityEntry entityEntry, Object[] state);
public void loadedStateDeletedNotification(EntityEntry entityEntry);
public void loadedStateDeletedNotification(EntityEntry entityEntry, Object[] deletedState);
public Object[] findCachedNaturalId(EntityPersister persister, Serializable pk);
@ -704,5 +704,4 @@ public interface PersistenceContext {
public void cacheNaturalIdResolution(EntityPersister persister, Serializable pk, Object[] naturalId, CachedNaturalIdValueSource valueSource);
public void evictNaturalIdResolution(EntityPersister persister, final Serializable pk, Object[] naturalIdValues );
}