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:
parent
b5ba7bef42
commit
f1a54aeadf
|
@ -92,7 +92,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction {
|
||||||
throw new AssertionFailure( "possible nonthreadsafe access to session" );
|
throw new AssertionFailure( "possible nonthreadsafe access to session" );
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.postInsert();
|
entry.postInsert( getState() );
|
||||||
|
|
||||||
if ( persister.hasInsertGeneratedProperties() ) {
|
if ( persister.hasInsertGeneratedProperties() ) {
|
||||||
persister.processInsertGeneratedProperties( id, instance, getState(), session );
|
persister.processInsertGeneratedProperties( id, instance, getState(), session );
|
||||||
|
|
|
@ -1705,54 +1705,53 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
// NATURAL ID RESOLUTION HANDLING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// NATURAL ID RESOLUTION HANDLING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadedStateInsertedNotification(EntityEntry entityEntry) {
|
public void loadedStateInsertedNotification(EntityEntry entityEntry, Object[] state) {
|
||||||
final EntityPersister persister = entityEntry.getPersister();
|
final EntityPersister persister = entityEntry.getPersister();
|
||||||
if ( !persister.hasNaturalIdentifier() ) {
|
if ( !persister.hasNaturalIdentifier() ) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Object[] naturalIdValues = getNaturalIdValues( entityEntry, persister );
|
final Object[] naturalIdValues = getNaturalIdValues( state, persister );
|
||||||
|
|
||||||
// cache
|
// cache
|
||||||
cacheNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues, CachedNaturalIdValueSource.INSERT );
|
cacheNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues, CachedNaturalIdValueSource.INSERT );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadedStateUpdatedNotification(EntityEntry entityEntry) {
|
public void loadedStateUpdatedNotification(EntityEntry entityEntry, Object[] state) {
|
||||||
final EntityPersister persister = entityEntry.getPersister();
|
final EntityPersister persister = entityEntry.getPersister();
|
||||||
if ( !persister.hasNaturalIdentifier() ) {
|
if ( !persister.hasNaturalIdentifier() ) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Object[] naturalIdValues = getNaturalIdValues( entityEntry, persister );
|
final Object[] naturalIdValues = getNaturalIdValues( state, persister );
|
||||||
|
|
||||||
// re-cache
|
// re-cache
|
||||||
cacheNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues, CachedNaturalIdValueSource.UPDATE );
|
cacheNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues, CachedNaturalIdValueSource.UPDATE );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadedStateDeletedNotification(EntityEntry entityEntry) {
|
public void loadedStateDeletedNotification(EntityEntry entityEntry, Object[] deletedState) {
|
||||||
final EntityPersister persister = entityEntry.getPersister();
|
final EntityPersister persister = entityEntry.getPersister();
|
||||||
if ( !persister.hasNaturalIdentifier() ) {
|
if ( !persister.hasNaturalIdentifier() ) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Object[] naturalIdValues = getNaturalIdValues( entityEntry, persister );
|
final Object[] naturalIdValues = getNaturalIdValues( deletedState, persister );
|
||||||
|
|
||||||
// evict from cache
|
// evict from cache
|
||||||
evictNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues );
|
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 int[] naturalIdPropertyIndexes = persister.getNaturalIdentifierProperties();
|
||||||
final Object[] naturalIdValues = new Object[naturalIdPropertyIndexes.length];
|
final Object[] naturalIdValues = new Object[naturalIdPropertyIndexes.length];
|
||||||
|
|
||||||
final Object[] loadedState = entityEntry.getLoadedState();
|
|
||||||
for ( int i = 0; i < naturalIdPropertyIndexes.length; i++ ) {
|
for ( int i = 0; i < naturalIdPropertyIndexes.length; i++ ) {
|
||||||
naturalIdValues[i] = loadedState[naturalIdPropertyIndexes[i]];
|
naturalIdValues[i] = state[naturalIdPropertyIndexes[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return naturalIdValues;
|
return naturalIdValues;
|
||||||
|
@ -1990,27 +1989,38 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void evictNaturalIdResolution(EntityPersister persister, final Serializable pk, Object[] deletedNaturalIdValues) {
|
||||||
public void evictNaturalIdResolution(EntityPersister persister, final Serializable pk, Object[] naturalIdValues) {
|
|
||||||
if ( !persister.hasNaturalIdentifier() ) {
|
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." );
|
throw new IllegalArgumentException( "Mismatch between expected number of natural-id values and found." );
|
||||||
}
|
}
|
||||||
|
|
||||||
NaturalIdResolutionCache entityNaturalIdResolutionCache = naturalIdResolutionCacheMap.get( persister );
|
NaturalIdResolutionCache entityNaturalIdResolutionCache = naturalIdResolutionCacheMap.get( persister );
|
||||||
|
Object[] sessionCachedNaturalIdValues = null;
|
||||||
if ( entityNaturalIdResolutionCache != null ) {
|
if ( entityNaturalIdResolutionCache != null ) {
|
||||||
final LocalNaturalIdCacheKey localNaturalIdCacheKey = new LocalNaturalIdCacheKey( persister,
|
final LocalNaturalIdCacheKey localNaturalIdCacheKey = entityNaturalIdResolutionCache.pkToNaturalIdMap
|
||||||
naturalIdValues );
|
.remove( pk );
|
||||||
entityNaturalIdResolutionCache.pkToNaturalIdMap.remove( pk );
|
if ( localNaturalIdCacheKey != null ) {
|
||||||
entityNaturalIdResolutionCache.naturalIdToPkMap.remove( localNaturalIdCacheKey );
|
entityNaturalIdResolutionCache.naturalIdToPkMap.remove( localNaturalIdCacheKey );
|
||||||
|
sessionCachedNaturalIdValues = localNaturalIdCacheKey.getValues();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( persister.hasNaturalIdCache() ) {
|
if ( persister.hasNaturalIdCache() ) {
|
||||||
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
|
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister
|
||||||
final NaturalIdCacheKey naturalIdCacheKey = new NaturalIdCacheKey( naturalIdValues, persister, session );
|
.getNaturalIdCacheAccessStrategy();
|
||||||
|
final NaturalIdCacheKey naturalIdCacheKey = new NaturalIdCacheKey( deletedNaturalIdValues, persister,
|
||||||
|
session );
|
||||||
naturalIdCacheAccessStrategy.evict( naturalIdCacheKey );
|
naturalIdCacheAccessStrategy.evict( naturalIdCacheKey );
|
||||||
|
|
||||||
|
if ( sessionCachedNaturalIdValues != null
|
||||||
|
&& !Arrays.equals( sessionCachedNaturalIdValues, deletedNaturalIdValues ) ) {
|
||||||
|
final NaturalIdCacheKey sessionNaturalIdCacheKey = new NaturalIdCacheKey( sessionCachedNaturalIdValues,
|
||||||
|
persister, session );
|
||||||
|
naturalIdCacheAccessStrategy.evict( sessionNaturalIdCacheKey );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,7 +241,7 @@ public final class EntityEntry implements Serializable {
|
||||||
.getCustomEntityDirtinessStrategy()
|
.getCustomEntityDirtinessStrategy()
|
||||||
.resetDirty( entity, getPersister(), (Session) persistenceContext.getSession() );
|
.resetDirty( entity, getPersister(), (Session) persistenceContext.getSession() );
|
||||||
|
|
||||||
notifyLoadedStateUpdated();
|
notifyLoadedStateUpdated( updatedState );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -253,17 +253,17 @@ public final class EntityEntry implements Serializable {
|
||||||
status = Status.GONE;
|
status = Status.GONE;
|
||||||
existsInDatabase = false;
|
existsInDatabase = false;
|
||||||
|
|
||||||
notifyLoadedStateDeleted();
|
notifyLoadedStateDeleted( deletedState );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* After actually inserting a row, record the fact that the instance exists on the
|
* After actually inserting a row, record the fact that the instance exists on the
|
||||||
* database (needed for identity-column key generation)
|
* database (needed for identity-column key generation)
|
||||||
*/
|
*/
|
||||||
public void postInsert() {
|
public void postInsert(Object[] insertedState) {
|
||||||
existsInDatabase = true;
|
existsInDatabase = true;
|
||||||
|
|
||||||
notifyLoadedStateInserted();
|
notifyLoadedStateInserted( insertedState );
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNullifiable(boolean earlyInsert, SessionImplementor session) {
|
public boolean isNullifiable(boolean earlyInsert, SessionImplementor session) {
|
||||||
|
@ -360,7 +360,7 @@ public final class EntityEntry implements Serializable {
|
||||||
}
|
}
|
||||||
setStatus( Status.MANAGED );
|
setStatus( Status.MANAGED );
|
||||||
loadedState = getPersister().getPropertyValues( entity );
|
loadedState = getPersister().getPropertyValues( entity );
|
||||||
notifyLoadedStateUpdated();
|
notifyLoadedStateUpdated( loadedState );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,28 +374,28 @@ public final class EntityEntry implements Serializable {
|
||||||
return loadedWithLazyPropertiesUnfetched;
|
return loadedWithLazyPropertiesUnfetched;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyLoadedStateUpdated() {
|
private void notifyLoadedStateUpdated(Object[] state) {
|
||||||
if ( persistenceContext == null ) {
|
if ( persistenceContext == null ) {
|
||||||
throw new HibernateException( "PersistenceContext was null on attempt to update loaded state" );
|
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 ) {
|
if ( persistenceContext == null ) {
|
||||||
throw new HibernateException( "PersistenceContext was null on attempt to insert loaded state" );
|
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 ) {
|
if ( persistenceContext == null ) {
|
||||||
throw new HibernateException( "PersistenceContext was null on attempt to delete loaded state" );
|
throw new HibernateException( "PersistenceContext was null on attempt to delete loaded state" );
|
||||||
}
|
}
|
||||||
|
|
||||||
persistenceContext.loadedStateDeletedNotification( this );
|
persistenceContext.loadedStateDeletedNotification( this, deletedState );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -683,11 +683,11 @@ public interface PersistenceContext {
|
||||||
*/
|
*/
|
||||||
public boolean wasInsertedDuringTransaction(EntityPersister persister, Serializable id);
|
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);
|
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 cacheNaturalIdResolution(EntityPersister persister, Serializable pk, Object[] naturalId, CachedNaturalIdValueSource valueSource);
|
||||||
|
|
||||||
public void evictNaturalIdResolution(EntityPersister persister, final Serializable pk, Object[] naturalIdValues );
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue