minor code cleanups to Actions
This commit is contained in:
parent
a11ebdeefc
commit
8f9b998894
|
@ -113,7 +113,7 @@ public abstract class AbstractEntityInsertAction extends EntityAction {
|
||||||
* @see #makeEntityManaged()
|
* @see #makeEntityManaged()
|
||||||
*/
|
*/
|
||||||
protected final void nullifyTransientReferencesIfNotAlready() {
|
protected final void nullifyTransientReferencesIfNotAlready() {
|
||||||
if ( ! areTransientReferencesNullified ) {
|
if ( !areTransientReferencesNullified ) {
|
||||||
new ForeignKeys.Nullifier( getInstance(), false, isEarlyInsert(), getSession(), getPersister() )
|
new ForeignKeys.Nullifier( getInstance(), false, isEarlyInsert(), getSession(), getPersister() )
|
||||||
.nullifyTransientReferences( getState() );
|
.nullifyTransientReferences( getState() );
|
||||||
new Nullability( getSession() ).checkNullability( getState(), getPersister(), false );
|
new Nullability( getSession() ).checkNullability( getState(), getPersister(), false );
|
||||||
|
@ -210,28 +210,25 @@ public abstract class AbstractEntityInsertAction extends EntityAction {
|
||||||
*/
|
*/
|
||||||
public void handleNaturalIdPostSaveNotifications(Object generatedId) {
|
public void handleNaturalIdPostSaveNotifications(Object generatedId) {
|
||||||
final NaturalIdMapping naturalIdMapping = getPersister().getNaturalIdMapping();
|
final NaturalIdMapping naturalIdMapping = getPersister().getNaturalIdMapping();
|
||||||
if ( naturalIdMapping == null ) {
|
if ( naturalIdMapping != null ) {
|
||||||
return;
|
final Object naturalIdValues = naturalIdMapping.extractNaturalIdFromEntityState( state, getSession() );
|
||||||
}
|
if ( isEarlyInsert() ) {
|
||||||
|
// with early insert, we still need to add a local (transactional) natural id cross-reference
|
||||||
final Object naturalIdValues = naturalIdMapping.extractNaturalIdFromEntityState( state, getSession() );
|
getSession().getPersistenceContextInternal().getNaturalIdResolutions().manageLocalResolution(
|
||||||
|
generatedId,
|
||||||
if ( isEarlyInsert() ) {
|
naturalIdValues,
|
||||||
// with early insert, we still need to add a local (transactional) natural id cross-reference
|
getPersister(),
|
||||||
getSession().getPersistenceContextInternal().getNaturalIdResolutions().manageLocalResolution(
|
CachedNaturalIdValueSource.INSERT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// after save, we need to manage the shared cache entries
|
||||||
|
getSession().getPersistenceContextInternal().getNaturalIdResolutions().manageSharedResolution(
|
||||||
generatedId,
|
generatedId,
|
||||||
naturalIdValues,
|
naturalIdValues,
|
||||||
|
null,
|
||||||
getPersister(),
|
getPersister(),
|
||||||
CachedNaturalIdValueSource.INSERT
|
CachedNaturalIdValueSource.INSERT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// after save, we need to manage the shared cache entries
|
|
||||||
getSession().getPersistenceContextInternal().getNaturalIdResolutions().manageSharedResolution(
|
|
||||||
generatedId,
|
|
||||||
naturalIdValues,
|
|
||||||
null,
|
|
||||||
getPersister(),
|
|
||||||
CachedNaturalIdValueSource.INSERT
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class BulkOperationCleanupAction implements Executable, Serializable {
|
public class BulkOperationCleanupAction implements Executable, Serializable {
|
||||||
|
|
||||||
private final Serializable[] affectedTableSpaces;
|
private final Serializable[] affectedTableSpaces;
|
||||||
|
|
||||||
private final Set<EntityCleanup> entityCleanups = new HashSet<>();
|
private final Set<EntityCleanup> entityCleanups = new HashSet<>();
|
||||||
|
@ -63,7 +64,6 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
||||||
* @param affectedQueryables The affected entity persisters.
|
* @param affectedQueryables The affected entity persisters.
|
||||||
*/
|
*/
|
||||||
public BulkOperationCleanupAction(SharedSessionContractImplementor session, EntityPersister... affectedQueryables) {
|
public BulkOperationCleanupAction(SharedSessionContractImplementor session, EntityPersister... affectedQueryables) {
|
||||||
final SessionFactoryImplementor factory = session.getFactory();
|
|
||||||
final LinkedHashSet<String> spacesList = new LinkedHashSet<>();
|
final LinkedHashSet<String> spacesList = new LinkedHashSet<>();
|
||||||
for ( EntityPersister persister : affectedQueryables ) {
|
for ( EntityPersister persister : affectedQueryables ) {
|
||||||
Collections.addAll( spacesList, (String[]) persister.getQuerySpaces() );
|
Collections.addAll( spacesList, (String[]) persister.getQuerySpaces() );
|
||||||
|
@ -81,17 +81,14 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final MappingMetamodelImplementor mappingMetamodel = factory.getRuntimeMetamodels().getMappingMetamodel();
|
final MappingMetamodelImplementor mappingMetamodel = session.getFactory().getRuntimeMetamodels().getMappingMetamodel();
|
||||||
final Set<String> roles = mappingMetamodel.getCollectionRolesByEntityParticipant( persister.getEntityName() );
|
final Set<String> roles = mappingMetamodel.getCollectionRolesByEntityParticipant( persister.getEntityName() );
|
||||||
if ( roles != null ) {
|
if ( roles != null ) {
|
||||||
for ( String role : roles ) {
|
for ( String role : roles ) {
|
||||||
final CollectionPersister collectionPersister = mappingMetamodel.getCollectionDescriptor( role );
|
final CollectionPersister collectionPersister = mappingMetamodel.getCollectionDescriptor( role );
|
||||||
if ( collectionPersister.hasCache() ) {
|
if ( collectionPersister.hasCache() ) {
|
||||||
collectionCleanups.add(
|
collectionCleanups.add(
|
||||||
new CollectionCleanup(
|
new CollectionCleanup( collectionPersister.getCacheAccessStrategy(), session )
|
||||||
collectionPersister.getCacheAccessStrategy(),
|
|
||||||
session
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,11 +100,12 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an action to cleanup "affected cache regions" based on a
|
* Constructs an action to cleanup "affected cache regions" based on a
|
||||||
* set of affected table spaces. This differs from {@link #BulkOperationCleanupAction(SharedSessionContractImplementor, EntityPersister[])}
|
* set of affected table spaces. This differs from
|
||||||
* in that here we have the affected <strong>table names</strong>. From those
|
* {@link #BulkOperationCleanupAction(SharedSessionContractImplementor, EntityPersister[])}
|
||||||
* we deduce the entity persisters which are affected based on the defined
|
* in that here we have the affected <strong>table names</strong>. From
|
||||||
* {@link EntityPersister#getQuerySpaces() table spaces}; and from there, we
|
* those we deduce the entity persisters which are affected based on the
|
||||||
* determine the affected collection regions based on any collections
|
* defined {@link EntityPersister#getQuerySpaces() table spaces}. Finally,
|
||||||
|
* we determine the affected collection regions based on any collections
|
||||||
* in which those entity persisters participate as elements/keys/etc.
|
* in which those entity persisters participate as elements/keys/etc.
|
||||||
*
|
*
|
||||||
* @param session The session to which this request is tied.
|
* @param session The session to which this request is tied.
|
||||||
|
@ -116,8 +114,7 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
||||||
public BulkOperationCleanupAction(SharedSessionContractImplementor session, Set<String> tableSpaces) {
|
public BulkOperationCleanupAction(SharedSessionContractImplementor session, Set<String> tableSpaces) {
|
||||||
final LinkedHashSet<String> spacesList = new LinkedHashSet<>( tableSpaces );
|
final LinkedHashSet<String> spacesList = new LinkedHashSet<>( tableSpaces );
|
||||||
|
|
||||||
final SessionFactoryImplementor factory = session.getFactory();
|
final MappingMetamodelImplementor metamodel = session.getFactory().getRuntimeMetamodels().getMappingMetamodel();
|
||||||
final MappingMetamodelImplementor metamodel = factory.getRuntimeMetamodels().getMappingMetamodel();
|
|
||||||
metamodel.forEachEntityDescriptor( (entityDescriptor) -> {
|
metamodel.forEachEntityDescriptor( (entityDescriptor) -> {
|
||||||
final String[] entitySpaces = (String[]) entityDescriptor.getQuerySpaces();
|
final String[] entitySpaces = (String[]) entityDescriptor.getQuerySpaces();
|
||||||
if ( affectedEntity( tableSpaces, entitySpaces ) ) {
|
if ( affectedEntity( tableSpaces, entitySpaces ) ) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.hibernate.pretty.MessageHelper;
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public abstract class CollectionAction implements Executable, Serializable, Comparable<CollectionAction> {
|
public abstract class CollectionAction implements Executable, Serializable, Comparable<CollectionAction> {
|
||||||
|
|
||||||
private transient CollectionPersister persister;
|
private transient CollectionPersister persister;
|
||||||
private transient SharedSessionContractImplementor session;
|
private transient SharedSessionContractImplementor session;
|
||||||
private final PersistentCollection<?> collection;
|
private final PersistentCollection<?> collection;
|
||||||
|
|
|
@ -41,7 +41,6 @@ public final class CollectionRecreateAction extends CollectionAction {
|
||||||
// this method is called when a new non-null collection is persisted
|
// this method is called when a new non-null collection is persisted
|
||||||
// or when an existing (non-null) collection is moved to a new owner
|
// or when an existing (non-null) collection is moved to a new owner
|
||||||
final PersistentCollection<?> collection = getCollection();
|
final PersistentCollection<?> collection = getCollection();
|
||||||
|
|
||||||
preRecreate();
|
preRecreate();
|
||||||
final SharedSessionContractImplementor session = getSession();
|
final SharedSessionContractImplementor session = getSession();
|
||||||
getPersister().recreate( collection, getKey(), session);
|
getPersister().recreate( collection, getKey(), session);
|
||||||
|
@ -56,9 +55,9 @@ public final class CollectionRecreateAction extends CollectionAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preRecreate() {
|
private void preRecreate() {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_PRE_COLLECTION_RECREATE
|
||||||
.eventListenerGroup_PRE_COLLECTION_RECREATE
|
.fireLazyEventOnEachListener( this::newPreCollectionRecreateEvent,
|
||||||
.fireLazyEventOnEachListener( this::newPreCollectionRecreateEvent, PreCollectionRecreateEventListener::onPreRecreateCollection );
|
PreCollectionRecreateEventListener::onPreRecreateCollection );
|
||||||
}
|
}
|
||||||
|
|
||||||
private PreCollectionRecreateEvent newPreCollectionRecreateEvent() {
|
private PreCollectionRecreateEvent newPreCollectionRecreateEvent() {
|
||||||
|
@ -66,9 +65,9 @@ public final class CollectionRecreateAction extends CollectionAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postRecreate() {
|
private void postRecreate() {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_POST_COLLECTION_RECREATE
|
||||||
.eventListenerGroup_POST_COLLECTION_RECREATE
|
.fireLazyEventOnEachListener( this::newPostCollectionRecreateEvent,
|
||||||
.fireLazyEventOnEachListener( this::newPostCollectionRecreateEvent, PostCollectionRecreateEventListener::onPostRecreateCollection );
|
PostCollectionRecreateEventListener::onPostRecreateCollection );
|
||||||
}
|
}
|
||||||
|
|
||||||
private PostCollectionRecreateEvent newPostCollectionRecreateEvent() {
|
private PostCollectionRecreateEvent newPostCollectionRecreateEvent() {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
* The action for removing a collection
|
* The action for removing a collection
|
||||||
*/
|
*/
|
||||||
public final class CollectionRemoveAction extends CollectionAction {
|
public final class CollectionRemoveAction extends CollectionAction {
|
||||||
|
|
||||||
private final Object affectedOwner;
|
private final Object affectedOwner;
|
||||||
private final boolean emptySnapshot;
|
private final boolean emptySnapshot;
|
||||||
|
|
||||||
|
@ -101,9 +102,7 @@ public final class CollectionRemoveAction extends CollectionAction {
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws HibernateException {
|
public void execute() throws HibernateException {
|
||||||
preRemove();
|
preRemove();
|
||||||
|
|
||||||
final SharedSessionContractImplementor session = getSession();
|
final SharedSessionContractImplementor session = getSession();
|
||||||
|
|
||||||
if ( !emptySnapshot ) {
|
if ( !emptySnapshot ) {
|
||||||
// an existing collection that was either nonempty or uninitialized
|
// an existing collection that was either nonempty or uninitialized
|
||||||
// is replaced by null or a different collection
|
// is replaced by null or a different collection
|
||||||
|
@ -111,12 +110,10 @@ public final class CollectionRemoveAction extends CollectionAction {
|
||||||
// knowing if the collection is actually empty without querying the db)
|
// knowing if the collection is actually empty without querying the db)
|
||||||
getPersister().remove( getKey(), session );
|
getPersister().remove( getKey(), session );
|
||||||
}
|
}
|
||||||
|
|
||||||
final PersistentCollection<?> collection = getCollection();
|
final PersistentCollection<?> collection = getCollection();
|
||||||
if ( collection != null ) {
|
if ( collection != null ) {
|
||||||
session.getPersistenceContextInternal().getCollectionEntry( collection ).afterAction( collection );
|
session.getPersistenceContextInternal().getCollectionEntry( collection ).afterAction( collection );
|
||||||
}
|
}
|
||||||
|
|
||||||
evict();
|
evict();
|
||||||
postRemove();
|
postRemove();
|
||||||
|
|
||||||
|
@ -127,9 +124,9 @@ public final class CollectionRemoveAction extends CollectionAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preRemove() {
|
private void preRemove() {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_PRE_COLLECTION_REMOVE
|
||||||
.eventListenerGroup_PRE_COLLECTION_REMOVE
|
.fireLazyEventOnEachListener( this::newPreCollectionRemoveEvent,
|
||||||
.fireLazyEventOnEachListener( this::newPreCollectionRemoveEvent, PreCollectionRemoveEventListener::onPreRemoveCollection );
|
PreCollectionRemoveEventListener::onPreRemoveCollection );
|
||||||
}
|
}
|
||||||
|
|
||||||
private PreCollectionRemoveEvent newPreCollectionRemoveEvent() {
|
private PreCollectionRemoveEvent newPreCollectionRemoveEvent() {
|
||||||
|
@ -142,9 +139,9 @@ public final class CollectionRemoveAction extends CollectionAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postRemove() {
|
private void postRemove() {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_POST_COLLECTION_REMOVE
|
||||||
.eventListenerGroup_POST_COLLECTION_REMOVE
|
.fireLazyEventOnEachListener( this::newPostCollectionRemoveEvent,
|
||||||
.fireLazyEventOnEachListener( this::newPostCollectionRemoveEvent, PostCollectionRemoveEventListener::onPostRemoveCollection );
|
PostCollectionRemoveEventListener::onPostRemoveCollection );
|
||||||
}
|
}
|
||||||
|
|
||||||
private PostCollectionRemoveEvent newPostCollectionRemoveEvent() {
|
private PostCollectionRemoveEvent newPostCollectionRemoveEvent() {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
* The action for updating a collection
|
* The action for updating a collection
|
||||||
*/
|
*/
|
||||||
public final class CollectionUpdateAction extends CollectionAction {
|
public final class CollectionUpdateAction extends CollectionAction {
|
||||||
|
|
||||||
private final boolean emptySnapshot;
|
private final boolean emptySnapshot;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,9 +69,8 @@ public final class CollectionUpdateAction extends CollectionAction {
|
||||||
}
|
}
|
||||||
else if ( collection.needsRecreate( persister ) ) {
|
else if ( collection.needsRecreate( persister ) ) {
|
||||||
if ( affectedByFilters ) {
|
if ( affectedByFilters ) {
|
||||||
throw new HibernateException(
|
throw new HibernateException( "cannot recreate collection while filter is enabled: "
|
||||||
"cannot recreate collection while filter is enabled: " +
|
+ MessageHelper.collectionInfoString( persister, collection, id, session )
|
||||||
MessageHelper.collectionInfoString( persister, collection, id, session )
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( !emptySnapshot ) {
|
if ( !emptySnapshot ) {
|
||||||
|
@ -95,9 +95,9 @@ public final class CollectionUpdateAction extends CollectionAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preUpdate() {
|
private void preUpdate() {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_PRE_COLLECTION_UPDATE
|
||||||
.eventListenerGroup_PRE_COLLECTION_UPDATE
|
.fireLazyEventOnEachListener( this::newPreCollectionUpdateEvent,
|
||||||
.fireLazyEventOnEachListener( this::newPreCollectionUpdateEvent, PreCollectionUpdateEventListener::onPreUpdateCollection );
|
PreCollectionUpdateEventListener::onPreUpdateCollection );
|
||||||
}
|
}
|
||||||
|
|
||||||
private PreCollectionUpdateEvent newPreCollectionUpdateEvent() {
|
private PreCollectionUpdateEvent newPreCollectionUpdateEvent() {
|
||||||
|
@ -109,9 +109,9 @@ public final class CollectionUpdateAction extends CollectionAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postUpdate() {
|
private void postUpdate() {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_POST_COLLECTION_UPDATE
|
||||||
.eventListenerGroup_POST_COLLECTION_UPDATE
|
.fireLazyEventOnEachListener( this::newPostCollectionUpdateEvent,
|
||||||
.fireLazyEventOnEachListener( this::newPostCollectionUpdateEvent, PostCollectionUpdateEventListener::onPostUpdateCollection );
|
PostCollectionUpdateEventListener::onPostUpdateCollection );
|
||||||
}
|
}
|
||||||
|
|
||||||
private PostCollectionUpdateEvent newPostCollectionUpdateEvent() {
|
private PostCollectionUpdateEvent newPostCollectionUpdateEvent() {
|
||||||
|
|
|
@ -106,9 +106,7 @@ public abstract class EntityAction
|
||||||
}
|
}
|
||||||
|
|
||||||
public final DelayedPostInsertIdentifier getDelayedId() {
|
public final DelayedPostInsertIdentifier getDelayedId() {
|
||||||
return id instanceof DelayedPostInsertIdentifier
|
return id instanceof DelayedPostInsertIdentifier ? (DelayedPostInsertIdentifier) id : null;
|
||||||
? (DelayedPostInsertIdentifier) id
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,13 +155,9 @@ public abstract class EntityAction
|
||||||
public int compareTo(EntityAction action) {
|
public int compareTo(EntityAction action) {
|
||||||
//sort first by entity name
|
//sort first by entity name
|
||||||
final int roleComparison = entityName.compareTo( action.entityName );
|
final int roleComparison = entityName.compareTo( action.entityName );
|
||||||
if ( roleComparison != 0 ) {
|
return roleComparison != 0 ? roleComparison
|
||||||
return roleComparison;
|
//then by id
|
||||||
}
|
: persister.getIdentifierType().compare( id, action.id );
|
||||||
else {
|
|
||||||
//then by id
|
|
||||||
return persister.getIdentifierType().compare( id, action.id );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -180,7 +174,7 @@ public abstract class EntityAction
|
||||||
// guard against NullPointerException
|
// guard against NullPointerException
|
||||||
if ( session != null ) {
|
if ( session != null ) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.persister = session.getFactory().getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor( entityName );
|
this.persister = session.getFactory().getMappingMetamodel().getEntityDescriptor( entityName );
|
||||||
this.instance = session.getPersistenceContext().getEntity( session.generateEntityKey( id, persister ) );
|
this.instance = session.getPersistenceContext().getEntity( session.generateEntityKey( id, persister ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class EntityDeleteAction extends EntityAction {
|
||||||
this.isCascadeDeleteEnabled = isCascadeDeleteEnabled;
|
this.isCascadeDeleteEnabled = isCascadeDeleteEnabled;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
|
||||||
NaturalIdMapping naturalIdMapping = persister.getNaturalIdMapping();
|
final NaturalIdMapping naturalIdMapping = persister.getNaturalIdMapping();
|
||||||
if ( naturalIdMapping != null ) {
|
if ( naturalIdMapping != null ) {
|
||||||
naturalIdValues = session.getPersistenceContextInternal().getNaturalIdResolutions()
|
naturalIdValues = session.getPersistenceContextInternal().getNaturalIdResolutions()
|
||||||
.removeLocalResolution(
|
.removeLocalResolution(
|
||||||
|
@ -79,10 +79,7 @@ public class EntityDeleteAction extends EntityAction {
|
||||||
* @param persister The entity persister
|
* @param persister The entity persister
|
||||||
* @param session The session
|
* @param session The session
|
||||||
*/
|
*/
|
||||||
public EntityDeleteAction(
|
public EntityDeleteAction(final Object id, final EntityPersister persister, final SessionImplementor session) {
|
||||||
final Object id,
|
|
||||||
final EntityPersister persister,
|
|
||||||
final SessionImplementor session) {
|
|
||||||
super( session, id, null, persister );
|
super( session, id, null, persister );
|
||||||
version = null;
|
version = null;
|
||||||
isCascadeDeleteEnabled = false;
|
isCascadeDeleteEnabled = false;
|
||||||
|
@ -128,15 +125,7 @@ public class EntityDeleteAction extends EntityAction {
|
||||||
|
|
||||||
final boolean veto = isInstanceLoaded() && preDelete();
|
final boolean veto = isInstanceLoaded() && preDelete();
|
||||||
|
|
||||||
final Object ck;
|
final Object ck = lockCacheItem();
|
||||||
if ( persister.canWriteToCache() ) {
|
|
||||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
|
||||||
ck = cache.generateCacheKey( id, persister, session.getFactory(), session.getTenantIdentifier() );
|
|
||||||
lock = cache.lockItem( session, ck, version );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ck = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isCascadeDeleteEnabled && !veto ) {
|
if ( !isCascadeDeleteEnabled && !veto ) {
|
||||||
persister.delete( id, version, instance, session );
|
persister.delete( id, version, instance, session );
|
||||||
|
@ -182,17 +171,11 @@ public class EntityDeleteAction extends EntityAction {
|
||||||
throw new AssertionFailure( "possible non-threadsafe access to session" );
|
throw new AssertionFailure( "possible non-threadsafe access to session" );
|
||||||
}
|
}
|
||||||
entry.postDelete();
|
entry.postDelete();
|
||||||
|
|
||||||
EntityKey key = entry.getEntityKey();
|
EntityKey key = entry.getEntityKey();
|
||||||
persistenceContext.removeEntity( key );
|
persistenceContext.removeEntity( key );
|
||||||
persistenceContext.removeProxy( key );
|
persistenceContext.removeProxy( key );
|
||||||
|
removeCacheItem( ck );
|
||||||
if ( persister.canWriteToCache() ) {
|
|
||||||
persister.getCacheAccessStrategy().remove( session, ck );
|
|
||||||
}
|
|
||||||
|
|
||||||
persistenceContext.getNaturalIdResolutions().removeSharedResolution( id, naturalIdValues, persister );
|
persistenceContext.getNaturalIdResolutions().removeSharedResolution( id, naturalIdValues, persister );
|
||||||
|
|
||||||
postDelete();
|
postDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,27 +186,27 @@ public class EntityDeleteAction extends EntityAction {
|
||||||
throw new AssertionFailure( "deleted proxy should be for an unloaded entity: " + key );
|
throw new AssertionFailure( "deleted proxy should be for an unloaded entity: " + key );
|
||||||
}
|
}
|
||||||
persistenceContext.removeProxy( key );
|
persistenceContext.removeProxy( key );
|
||||||
if ( persister.canWriteToCache() ) {
|
removeCacheItem( ck );
|
||||||
persister.getCacheAccessStrategy().remove( session, ck );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean preDelete() {
|
protected boolean preDelete() {
|
||||||
final EventListenerGroup<PreDeleteEventListener> listenerGroup = getFastSessionServices().eventListenerGroup_PRE_DELETE;
|
final EventListenerGroup<PreDeleteEventListener> listenerGroup
|
||||||
|
= getFastSessionServices().eventListenerGroup_PRE_DELETE;
|
||||||
if ( listenerGroup.isEmpty() ) {
|
if ( listenerGroup.isEmpty() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final PreDeleteEvent event = new PreDeleteEvent( getInstance(), getId(), state, getPersister(), eventSource() );
|
else {
|
||||||
boolean veto = false;
|
final PreDeleteEvent event = new PreDeleteEvent( getInstance(), getId(), state, getPersister(), eventSource() );
|
||||||
for ( PreDeleteEventListener listener : listenerGroup.listeners() ) {
|
boolean veto = false;
|
||||||
veto |= listener.onPreDelete( event );
|
for ( PreDeleteEventListener listener : listenerGroup.listeners() ) {
|
||||||
|
veto |= listener.onPreDelete( event );
|
||||||
|
}
|
||||||
|
return veto;
|
||||||
}
|
}
|
||||||
return veto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void postDelete() {
|
protected void postDelete() {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_POST_DELETE
|
||||||
.eventListenerGroup_POST_DELETE
|
|
||||||
.fireLazyEventOnEachListener( this::newPostDeleteEvent, PostDeleteEventListener::onPostDelete );
|
.fireLazyEventOnEachListener( this::newPostDeleteEvent, PostDeleteEventListener::onPostDelete );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,8 +221,8 @@ public class EntityDeleteAction extends EntityAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void postCommitDelete(boolean success) {
|
protected void postCommitDelete(boolean success) {
|
||||||
final EventListenerGroup<PostDeleteEventListener> eventListeners = getFastSessionServices()
|
final EventListenerGroup<PostDeleteEventListener> eventListeners
|
||||||
.eventListenerGroup_POST_COMMIT_DELETE;
|
= getFastSessionServices().eventListenerGroup_POST_COMMIT_DELETE;
|
||||||
if (success) {
|
if (success) {
|
||||||
eventListeners.fireLazyEventOnEachListener( this::newPostDeleteEvent, PostDeleteEventListener::onPostDelete );
|
eventListeners.fireLazyEventOnEachListener( this::newPostDeleteEvent, PostDeleteEventListener::onPostDelete );
|
||||||
}
|
}
|
||||||
|
@ -260,29 +243,53 @@ public class EntityDeleteAction extends EntityAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws HibernateException {
|
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws HibernateException {
|
||||||
EntityPersister entityPersister = getPersister();
|
unlockCacheItem();
|
||||||
if ( entityPersister.canWriteToCache() ) {
|
|
||||||
EntityDataAccess cache = entityPersister.getCacheAccessStrategy();
|
|
||||||
final Object ck = cache.generateCacheKey(
|
|
||||||
getId(),
|
|
||||||
entityPersister,
|
|
||||||
session.getFactory(),
|
|
||||||
session.getTenantIdentifier()
|
|
||||||
);
|
|
||||||
cache.unlockItem( session, ck, lock );
|
|
||||||
}
|
|
||||||
postCommitDelete( success );
|
postCommitDelete( success );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasPostCommitEventListeners() {
|
protected boolean hasPostCommitEventListeners() {
|
||||||
final EventListenerGroup<PostDeleteEventListener> group = getFastSessionServices().eventListenerGroup_POST_COMMIT_DELETE;
|
for ( PostDeleteEventListener listener: getFastSessionServices().eventListenerGroup_POST_COMMIT_DELETE.listeners() ) {
|
||||||
for ( PostDeleteEventListener listener : group.listeners() ) {
|
|
||||||
if ( listener.requiresPostCommitHandling( getPersister() ) ) {
|
if ( listener.requiresPostCommitHandling( getPersister() ) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object lockCacheItem() {
|
||||||
|
final EntityPersister persister = getPersister();
|
||||||
|
if ( persister.canWriteToCache() ) {
|
||||||
|
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||||
|
final SharedSessionContractImplementor session = getSession();
|
||||||
|
Object ck = cache.generateCacheKey( getId(), persister, session.getFactory(), session.getTenantIdentifier() );
|
||||||
|
lock = cache.lockItem( session, ck, getCurrentVersion() );
|
||||||
|
return ck;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unlockCacheItem() {
|
||||||
|
final EntityPersister persister = getPersister();
|
||||||
|
if ( persister.canWriteToCache() ) {
|
||||||
|
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||||
|
final SharedSessionContractImplementor session = getSession();
|
||||||
|
final Object ck = cache.generateCacheKey(
|
||||||
|
getId(),
|
||||||
|
persister,
|
||||||
|
session.getFactory(),
|
||||||
|
session.getTenantIdentifier()
|
||||||
|
);
|
||||||
|
cache.unlockItem( session, ck, lock );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeCacheItem(Object ck) {
|
||||||
|
final EntityPersister persister = getPersister();
|
||||||
|
if ( persister.canWriteToCache() ) {
|
||||||
|
persister.getCacheAccessStrategy().remove( getSession(), ck );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,12 +45,12 @@ public class EntityIdentityInsertAction extends AbstractEntityInsertAction {
|
||||||
* @throws HibernateException Indicates an illegal state
|
* @throws HibernateException Indicates an illegal state
|
||||||
*/
|
*/
|
||||||
public EntityIdentityInsertAction(
|
public EntityIdentityInsertAction(
|
||||||
Object[] state,
|
final Object[] state,
|
||||||
Object instance,
|
final Object instance,
|
||||||
EntityPersister persister,
|
final EntityPersister persister,
|
||||||
boolean isVersionIncrementDisabled,
|
final boolean isVersionIncrementDisabled,
|
||||||
SharedSessionContractImplementor session,
|
final SharedSessionContractImplementor session,
|
||||||
boolean isDelayed) {
|
final boolean isDelayed) {
|
||||||
super(
|
super(
|
||||||
isDelayed ? generateDelayedPostInsertIdentifier() : null,
|
isDelayed ? generateDelayedPostInsertIdentifier() : null,
|
||||||
state,
|
state,
|
||||||
|
@ -90,7 +90,6 @@ public class EntityIdentityInsertAction extends AbstractEntityInsertAction {
|
||||||
persistenceContext.checkUniqueness( entityKey, getInstance() );
|
persistenceContext.checkUniqueness( entityKey, getInstance() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//TODO: this bit actually has to be called after all cascades!
|
//TODO: this bit actually has to be called after all cascades!
|
||||||
// but since identity insert is called *synchronously*,
|
// but since identity insert is called *synchronously*,
|
||||||
// instead of asynchronously as other actions, it isn't
|
// instead of asynchronously as other actions, it isn't
|
||||||
|
@ -117,13 +116,13 @@ public class EntityIdentityInsertAction extends AbstractEntityInsertAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasPostCommitEventListeners() {
|
protected boolean hasPostCommitEventListeners() {
|
||||||
final EventListenerGroup<PostInsertEventListener> group = getFastSessionServices().eventListenerGroup_POST_COMMIT_INSERT;
|
final EventListenerGroup<PostInsertEventListener> group
|
||||||
|
= getFastSessionServices().eventListenerGroup_POST_COMMIT_INSERT;
|
||||||
for ( PostInsertEventListener listener : group.listeners() ) {
|
for ( PostInsertEventListener listener : group.listeners() ) {
|
||||||
if ( listener.requiresPostCommitHandling( getPersister() ) ) {
|
if ( listener.requiresPostCommitHandling( getPersister() ) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,10 +138,10 @@ public class EntityIdentityInsertAction extends AbstractEntityInsertAction {
|
||||||
|
|
||||||
protected void postInsert() {
|
protected void postInsert() {
|
||||||
if ( isDelayed ) {
|
if ( isDelayed ) {
|
||||||
eventSource().getPersistenceContextInternal().replaceDelayedEntityIdentityInsertKeys( delayedEntityKey, generatedId );
|
eventSource().getPersistenceContextInternal()
|
||||||
|
.replaceDelayedEntityIdentityInsertKeys( delayedEntityKey, generatedId );
|
||||||
}
|
}
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_POST_INSERT
|
||||||
.eventListenerGroup_POST_INSERT
|
|
||||||
.fireLazyEventOnEachListener( this::newPostInsertEvent, PostInsertEventListener::onPostInsert );
|
.fireLazyEventOnEachListener( this::newPostInsertEvent, PostInsertEventListener::onPostInsert );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,9 +156,9 @@ public class EntityIdentityInsertAction extends AbstractEntityInsertAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void postCommitInsert(boolean success) {
|
protected void postCommitInsert(boolean success) {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_POST_COMMIT_INSERT
|
||||||
.eventListenerGroup_POST_COMMIT_INSERT
|
.fireLazyEventOnEachListener( this::newPostInsertEvent,
|
||||||
.fireLazyEventOnEachListener( this::newPostInsertEvent, success ? PostInsertEventListener::onPostInsert : this::postCommitInsertOnFailure );
|
success ? PostInsertEventListener::onPostInsert : this::postCommitInsertOnFailure );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postCommitInsertOnFailure(PostInsertEventListener listener, PostInsertEvent event) {
|
private void postCommitInsertOnFailure(PostInsertEventListener listener, PostInsertEvent event) {
|
||||||
|
@ -173,17 +172,20 @@ public class EntityIdentityInsertAction extends AbstractEntityInsertAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean preInsert() {
|
protected boolean preInsert() {
|
||||||
final EventListenerGroup<PreInsertEventListener> listenerGroup = getFastSessionServices().eventListenerGroup_PRE_INSERT;
|
final EventListenerGroup<PreInsertEventListener> listenerGroup
|
||||||
|
= getFastSessionServices().eventListenerGroup_PRE_INSERT;
|
||||||
if ( listenerGroup.isEmpty() ) {
|
if ( listenerGroup.isEmpty() ) {
|
||||||
// NO_VETO
|
// NO_VETO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean veto = false;
|
else {
|
||||||
final PreInsertEvent event = new PreInsertEvent( getInstance(), null, getState(), getPersister(), eventSource() );
|
final PreInsertEvent event = new PreInsertEvent( getInstance(), null, getState(), getPersister(), eventSource() );
|
||||||
for ( PreInsertEventListener listener : listenerGroup.listeners() ) {
|
boolean veto = false;
|
||||||
veto |= listener.onPreInsert( event );
|
for ( PreInsertEventListener listener : listenerGroup.listeners() ) {
|
||||||
|
veto |= listener.onPreInsert( event );
|
||||||
|
}
|
||||||
|
return veto;
|
||||||
}
|
}
|
||||||
return veto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -218,9 +220,11 @@ public class EntityIdentityInsertAction extends AbstractEntityInsertAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EntityKey generateDelayedEntityKey() {
|
protected EntityKey generateDelayedEntityKey() {
|
||||||
if ( !isDelayed ) {
|
if ( isDelayed ) {
|
||||||
|
return getSession().generateEntityKey( getDelayedId(), getPersister() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
throw new AssertionFailure( "cannot request delayed entity-key for early-insert post-insert-id generation" );
|
throw new AssertionFailure( "cannot request delayed entity-key for early-insert post-insert-id generation" );
|
||||||
}
|
}
|
||||||
return getSession().generateEntityKey( getDelayedId(), getPersister() );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
* @see EntityIdentityInsertAction
|
* @see EntityIdentityInsertAction
|
||||||
*/
|
*/
|
||||||
public class EntityInsertAction extends AbstractEntityInsertAction {
|
public class EntityInsertAction extends AbstractEntityInsertAction {
|
||||||
|
|
||||||
private Object version;
|
private Object version;
|
||||||
private Object cacheEntry;
|
private Object cacheEntry;
|
||||||
|
|
||||||
|
@ -47,13 +48,13 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
|
||||||
* @param session The session
|
* @param session The session
|
||||||
*/
|
*/
|
||||||
public EntityInsertAction(
|
public EntityInsertAction(
|
||||||
Object id,
|
final Object id,
|
||||||
Object[] state,
|
final Object[] state,
|
||||||
Object instance,
|
final Object instance,
|
||||||
Object version,
|
final Object version,
|
||||||
EntityPersister persister,
|
final EntityPersister persister,
|
||||||
boolean isVersionIncrementDisabled,
|
final boolean isVersionIncrementDisabled,
|
||||||
SharedSessionContractImplementor session) {
|
final SharedSessionContractImplementor session) {
|
||||||
super( id, state, instance, isVersionIncrementDisabled, persister, session );
|
super( id, state, instance, isVersionIncrementDisabled, persister, session );
|
||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
@ -88,67 +89,31 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
|
||||||
public void execute() throws HibernateException {
|
public void execute() throws HibernateException {
|
||||||
nullifyTransientReferencesIfNotAlready();
|
nullifyTransientReferencesIfNotAlready();
|
||||||
|
|
||||||
final EntityPersister persister = getPersister();
|
|
||||||
final SharedSessionContractImplementor session = getSession();
|
|
||||||
final Object instance = getInstance();
|
|
||||||
final Object id = getId();
|
|
||||||
|
|
||||||
final boolean veto = preInsert();
|
|
||||||
|
|
||||||
// Don't need to lock the cache here, since if someone
|
// Don't need to lock the cache here, since if someone
|
||||||
// else inserted the same pk first, the insert would fail
|
// else inserted the same pk first, the insert would fail
|
||||||
|
|
||||||
|
final SharedSessionContractImplementor session = getSession();
|
||||||
|
final Object id = getId();
|
||||||
|
final boolean veto = preInsert();
|
||||||
if ( !veto ) {
|
if ( !veto ) {
|
||||||
|
final EntityPersister persister = getPersister();
|
||||||
|
final Object instance = getInstance();
|
||||||
persister.insert( id, getState(), instance, session );
|
persister.insert( id, getState(), instance, session );
|
||||||
PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
||||||
final EntityEntry entry = persistenceContext.getEntry( instance );
|
final EntityEntry entry = persistenceContext.getEntry( instance );
|
||||||
if ( entry == null ) {
|
if ( entry == null ) {
|
||||||
throw new AssertionFailure( "possible non-threadsafe access to session" );
|
throw new AssertionFailure( "possible non-threadsafe access to session" );
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.postInsert( getState() );
|
entry.postInsert( getState() );
|
||||||
|
handleGeneratedProperties( entry );
|
||||||
if ( persister.hasInsertGeneratedProperties() ) {
|
|
||||||
persister.processInsertGeneratedProperties( id, instance, getState(), session );
|
|
||||||
if ( persister.isVersionPropertyGenerated() ) {
|
|
||||||
version = Versioning.getVersion( getState(), persister );
|
|
||||||
}
|
|
||||||
entry.postUpdate( instance, getState(), version );
|
|
||||||
}
|
|
||||||
|
|
||||||
persistenceContext.registerInsertedKey( persister, getId() );
|
persistenceContext.registerInsertedKey( persister, getId() );
|
||||||
addCollectionsByKeyToPersistenceContext( persistenceContext, getState() );
|
addCollectionsByKeyToPersistenceContext( persistenceContext, getState() );
|
||||||
}
|
}
|
||||||
|
putCacheIfNecessary();
|
||||||
final SessionFactoryImplementor factory = session.getFactory();
|
|
||||||
|
|
||||||
final StatisticsImplementor statistics = factory.getStatistics();
|
|
||||||
if ( isCachePutEnabled( persister, session ) ) {
|
|
||||||
final CacheEntry ce = persister.buildCacheEntry(
|
|
||||||
instance,
|
|
||||||
getState(),
|
|
||||||
version,
|
|
||||||
session
|
|
||||||
);
|
|
||||||
cacheEntry = persister.getCacheEntryStructure().structure( ce );
|
|
||||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
|
||||||
final Object ck = cache.generateCacheKey( id, persister, factory, session.getTenantIdentifier() );
|
|
||||||
|
|
||||||
final boolean put = cacheInsert( persister, ck );
|
|
||||||
|
|
||||||
if ( put && statistics.isStatisticsEnabled() ) {
|
|
||||||
statistics.entityCachePut(
|
|
||||||
StatsHelper.INSTANCE.getRootEntityRole( persister ),
|
|
||||||
cache.getRegion().getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleNaturalIdPostSaveNotifications( id );
|
handleNaturalIdPostSaveNotifications( id );
|
||||||
|
|
||||||
postInsert();
|
postInsert();
|
||||||
|
|
||||||
|
final StatisticsImplementor statistics = session.getFactory().getStatistics();
|
||||||
if ( statistics.isStatisticsEnabled() && !veto ) {
|
if ( statistics.isStatisticsEnabled() && !veto ) {
|
||||||
statistics.insertEntity( getPersister().getEntityName() );
|
statistics.insertEntity( getPersister().getEntityName() );
|
||||||
}
|
}
|
||||||
|
@ -156,11 +121,44 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
|
||||||
markExecuted();
|
markExecuted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleGeneratedProperties(EntityEntry entry) {
|
||||||
|
final EntityPersister persister = getPersister();
|
||||||
|
if ( persister.hasInsertGeneratedProperties() ) {
|
||||||
|
final Object instance = getInstance();
|
||||||
|
persister.processInsertGeneratedProperties( getId(), instance, getState(), getSession() );
|
||||||
|
if ( persister.isVersionPropertyGenerated() ) {
|
||||||
|
version = Versioning.getVersion( getState(), persister);
|
||||||
|
}
|
||||||
|
entry.postUpdate( instance, getState(), version );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putCacheIfNecessary() {
|
||||||
|
final EntityPersister persister = getPersister();
|
||||||
|
final SharedSessionContractImplementor session = getSession();
|
||||||
|
if ( isCachePutEnabled( persister, session ) ) {
|
||||||
|
final SessionFactoryImplementor factory = session.getFactory();
|
||||||
|
final CacheEntry ce = persister.buildCacheEntry( getInstance(), getState(), version, session );
|
||||||
|
cacheEntry = persister.getCacheEntryStructure().structure( ce );
|
||||||
|
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||||
|
final Object ck = cache.generateCacheKey( getId(), persister, factory, session.getTenantIdentifier() );
|
||||||
|
final boolean put = cacheInsert( persister, ck );
|
||||||
|
|
||||||
|
final StatisticsImplementor statistics = factory.getStatistics();
|
||||||
|
if ( put && statistics.isStatisticsEnabled() ) {
|
||||||
|
statistics.entityCachePut(
|
||||||
|
StatsHelper.INSTANCE.getRootEntityRole( persister ),
|
||||||
|
cache.getRegion().getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean cacheInsert(EntityPersister persister, Object ck) {
|
protected boolean cacheInsert(EntityPersister persister, Object ck) {
|
||||||
SharedSessionContractImplementor session = getSession();
|
SharedSessionContractImplementor session = getSession();
|
||||||
try {
|
try {
|
||||||
session.getEventListenerManager().cachePutStart();
|
session.getEventListenerManager().cachePutStart();
|
||||||
return persister.getCacheAccessStrategy().insert( session, ck, cacheEntry, version);
|
return persister.getCacheAccessStrategy().insert( session, ck, cacheEntry, version );
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
session.getEventListenerManager().cachePutEnd();
|
session.getEventListenerManager().cachePutEnd();
|
||||||
|
@ -184,9 +182,9 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void postCommitInsert(boolean success) {
|
protected void postCommitInsert(boolean success) {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_POST_COMMIT_INSERT
|
||||||
.eventListenerGroup_POST_COMMIT_INSERT
|
.fireLazyEventOnEachListener( this::newPostInsertEvent,
|
||||||
.fireLazyEventOnEachListener( this::newPostInsertEvent, success ? PostInsertEventListener::onPostInsert : this::postCommitOnFailure );
|
success ? PostInsertEventListener::onPostInsert : this::postCommitOnFailure );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postCommitOnFailure(PostInsertEventListener listener, PostInsertEvent event) {
|
private void postCommitOnFailure(PostInsertEventListener listener, PostInsertEvent event) {
|
||||||
|
@ -202,7 +200,8 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
|
||||||
protected boolean preInsert() {
|
protected boolean preInsert() {
|
||||||
boolean veto = false;
|
boolean veto = false;
|
||||||
|
|
||||||
final EventListenerGroup<PreInsertEventListener> listenerGroup = getFastSessionServices().eventListenerGroup_PRE_INSERT;
|
final EventListenerGroup<PreInsertEventListener> listenerGroup
|
||||||
|
= getFastSessionServices().eventListenerGroup_PRE_INSERT;
|
||||||
if ( listenerGroup.isEmpty() ) {
|
if ( listenerGroup.isEmpty() ) {
|
||||||
return veto;
|
return veto;
|
||||||
}
|
}
|
||||||
|
@ -247,7 +246,8 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasPostCommitEventListeners() {
|
protected boolean hasPostCommitEventListeners() {
|
||||||
final EventListenerGroup<PostInsertEventListener> group = getFastSessionServices().eventListenerGroup_POST_COMMIT_INSERT;
|
final EventListenerGroup<PostInsertEventListener> group
|
||||||
|
= getFastSessionServices().eventListenerGroup_POST_COMMIT_INSERT;
|
||||||
for ( PostInsertEventListener listener : group.listeners() ) {
|
for ( PostInsertEventListener listener : group.listeners() ) {
|
||||||
if ( listener.requiresPostCommitHandling( getPersister() ) ) {
|
if ( listener.requiresPostCommitHandling( getPersister() ) ) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -258,8 +258,8 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
|
||||||
|
|
||||||
protected boolean isCachePutEnabled(EntityPersister persister, SharedSessionContractImplementor session) {
|
protected boolean isCachePutEnabled(EntityPersister persister, SharedSessionContractImplementor session) {
|
||||||
return persister.canWriteToCache()
|
return persister.canWriteToCache()
|
||||||
&& !persister.isCacheInvalidationRequired()
|
&& !persister.isCacheInvalidationRequired()
|
||||||
&& session.getCacheMode().isPutEnabled();
|
&& session.getCacheMode().isPutEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import org.hibernate.cache.spi.entry.CacheEntry;
|
||||||
import org.hibernate.engine.internal.Versioning;
|
import org.hibernate.engine.internal.Versioning;
|
||||||
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
|
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
|
||||||
import org.hibernate.engine.spi.SessionEventListenerManager;
|
import org.hibernate.engine.spi.SessionEventListenerManager;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
@ -37,6 +36,7 @@ import org.hibernate.type.TypeHelper;
|
||||||
* The action for performing entity updates.
|
* The action for performing entity updates.
|
||||||
*/
|
*/
|
||||||
public class EntityUpdateAction extends EntityAction {
|
public class EntityUpdateAction extends EntityAction {
|
||||||
|
|
||||||
private final Object[] state;
|
private final Object[] state;
|
||||||
private final Object[] previousState;
|
private final Object[] previousState;
|
||||||
private final Object previousVersion;
|
private final Object previousVersion;
|
||||||
|
@ -91,7 +91,7 @@ public class EntityUpdateAction extends EntityAction {
|
||||||
previousNaturalIdValues = null;
|
previousNaturalIdValues = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.previousNaturalIdValues = determinePreviousNaturalIdValues( persister, naturalIdMapping, id, previousState, session );
|
previousNaturalIdValues = determinePreviousNaturalIdValues( persister, naturalIdMapping, id, previousState, session );
|
||||||
session.getPersistenceContextInternal().getNaturalIdResolutions().manageLocalResolution(
|
session.getPersistenceContextInternal().getNaturalIdResolutions().manageLocalResolution(
|
||||||
id,
|
id,
|
||||||
naturalIdMapping.extractNaturalIdFromEntityState( state, session ),
|
naturalIdMapping.extractNaturalIdFromEntityState( state, session ),
|
||||||
|
@ -107,12 +107,9 @@ public class EntityUpdateAction extends EntityAction {
|
||||||
Object id,
|
Object id,
|
||||||
Object[] previousState,
|
Object[] previousState,
|
||||||
SharedSessionContractImplementor session) {
|
SharedSessionContractImplementor session) {
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
return previousState == null
|
||||||
if ( previousState != null ) {
|
? session.getPersistenceContextInternal().getNaturalIdSnapshot( id, persister )
|
||||||
return naturalIdMapping.extractNaturalIdFromEntityState( previousState, session );
|
: naturalIdMapping.extractNaturalIdFromEntityState( previousState, session );
|
||||||
}
|
|
||||||
|
|
||||||
return persistenceContext.getNaturalIdSnapshot( id, persister );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object[] getState() {
|
public Object[] getState() {
|
||||||
|
@ -129,56 +126,73 @@ public class EntityUpdateAction extends EntityAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws HibernateException {
|
public void execute() throws HibernateException {
|
||||||
final Object id = getId();
|
if ( !preUpdate() ) {
|
||||||
|
final EntityPersister persister = getPersister();
|
||||||
|
final SharedSessionContractImplementor session = getSession();
|
||||||
|
final Object id = getId();
|
||||||
|
final Object instance = getInstance();
|
||||||
|
final Object previousVersion = getPreviousVersion();
|
||||||
|
final Object ck = lockCacheItem( previousVersion );
|
||||||
|
persister.update( id, state, dirtyFields, hasDirtyCollection, previousState, previousVersion, instance, rowId, session );
|
||||||
|
final EntityEntry entry = session.getPersistenceContextInternal().getEntry( instance );
|
||||||
|
if ( entry == null ) {
|
||||||
|
throw new AssertionFailure( "possible non thread safe access to session" );
|
||||||
|
}
|
||||||
|
handleGeneratedProperties( entry );
|
||||||
|
updateCacheItem( previousVersion, ck, entry );
|
||||||
|
handleNaturalIdResolutions( persister, session, id );
|
||||||
|
postUpdate();
|
||||||
|
|
||||||
|
final StatisticsImplementor statistics = session.getFactory().getStatistics();
|
||||||
|
if ( statistics.isStatisticsEnabled() ) {
|
||||||
|
statistics.updateEntity( getPersister().getEntityName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNaturalIdResolutions(EntityPersister persister, SharedSessionContractImplementor session, Object id) {
|
||||||
|
if ( naturalIdMapping != null ) {
|
||||||
|
session.getPersistenceContextInternal().getNaturalIdResolutions().manageSharedResolution(
|
||||||
|
id,
|
||||||
|
naturalIdMapping.extractNaturalIdFromEntityState( state, session),
|
||||||
|
previousNaturalIdValues,
|
||||||
|
persister,
|
||||||
|
CachedNaturalIdValueSource.UPDATE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCacheItem(Object previousVersion, Object ck, EntityEntry entry) {
|
||||||
|
final EntityPersister persister = getPersister();
|
||||||
|
if ( persister.canWriteToCache() ) {
|
||||||
|
final SharedSessionContractImplementor session = getSession();
|
||||||
|
if ( persister.isCacheInvalidationRequired() || entry.getStatus() != Status.MANAGED ) {
|
||||||
|
persister.getCacheAccessStrategy().remove( session, ck );
|
||||||
|
}
|
||||||
|
else if ( session.getCacheMode().isPutEnabled() ) {
|
||||||
|
//TODO: inefficient if that cache is just going to ignore the updated state!
|
||||||
|
final CacheEntry ce = persister.buildCacheEntry( getInstance(), state, nextVersion, getSession() );
|
||||||
|
cacheEntry = persister.getCacheEntryStructure().structure( ce );
|
||||||
|
final boolean put = updateCache( persister, previousVersion, ck );
|
||||||
|
|
||||||
|
final StatisticsImplementor statistics = session.getFactory().getStatistics();
|
||||||
|
if ( put && statistics.isStatisticsEnabled() ) {
|
||||||
|
statistics.entityCachePut(
|
||||||
|
StatsHelper.INSTANCE.getRootEntityRole( persister ),
|
||||||
|
getPersister().getCacheAccessStrategy().getRegion().getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleGeneratedProperties(EntityEntry entry) {
|
||||||
final EntityPersister persister = getPersister();
|
final EntityPersister persister = getPersister();
|
||||||
final SharedSessionContractImplementor session = getSession();
|
|
||||||
final Object instance = getInstance();
|
final Object instance = getInstance();
|
||||||
|
|
||||||
if ( preUpdate() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final SessionFactoryImplementor factory = session.getFactory();
|
|
||||||
Object previousVersion = this.previousVersion;
|
|
||||||
if ( persister.isVersionPropertyGenerated() ) {
|
|
||||||
// we need to grab the version value from the entity, otherwise
|
|
||||||
// we have issues with generated-version entities that may have
|
|
||||||
// multiple actions queued during the same flush
|
|
||||||
previousVersion = persister.getVersion( instance );
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object ck;
|
|
||||||
if ( persister.canWriteToCache() ) {
|
|
||||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
|
||||||
ck = cache.generateCacheKey(
|
|
||||||
id,
|
|
||||||
persister,
|
|
||||||
factory,
|
|
||||||
session.getTenantIdentifier()
|
|
||||||
);
|
|
||||||
lock = cache.lockItem( session, ck, previousVersion );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ck = null;
|
|
||||||
}
|
|
||||||
persister.update(
|
|
||||||
id,
|
|
||||||
state,
|
|
||||||
dirtyFields,
|
|
||||||
hasDirtyCollection,
|
|
||||||
previousState,
|
|
||||||
previousVersion,
|
|
||||||
instance,
|
|
||||||
rowId,
|
|
||||||
session
|
|
||||||
);
|
|
||||||
|
|
||||||
final EntityEntry entry = session.getPersistenceContextInternal().getEntry( instance );
|
|
||||||
if ( entry == null ) {
|
|
||||||
throw new AssertionFailure( "possible non thread safe access to session" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( entry.getStatus() == Status.MANAGED || persister.isVersionPropertyGenerated() ) {
|
if ( entry.getStatus() == Status.MANAGED || persister.isVersionPropertyGenerated() ) {
|
||||||
|
final SharedSessionContractImplementor session = getSession();
|
||||||
|
final Object id = getId();
|
||||||
// get the updated snapshot of the entity state by cloning current state;
|
// get the updated snapshot of the entity state by cloning current state;
|
||||||
// it is safe to copy in place, since by this time no-one else (should have)
|
// it is safe to copy in place, since by this time no-one else (should have)
|
||||||
// has a reference to the array
|
// has a reference to the array
|
||||||
|
@ -194,7 +208,7 @@ public class EntityUpdateAction extends EntityAction {
|
||||||
// values...
|
// values...
|
||||||
persister.processUpdateGeneratedProperties( id, instance, state, session );
|
persister.processUpdateGeneratedProperties( id, instance, state, session );
|
||||||
if ( persister.isVersionPropertyGenerated() ) {
|
if ( persister.isVersionPropertyGenerated() ) {
|
||||||
nextVersion = Versioning.getVersion( state, persister );
|
nextVersion = Versioning.getVersion( state, persister);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// have the entity entry doAfterTransactionCompletion post-update processing, passing it the
|
// have the entity entry doAfterTransactionCompletion post-update processing, passing it the
|
||||||
|
@ -207,52 +221,47 @@ public class EntityUpdateAction extends EntityAction {
|
||||||
final boolean isImpliedOptimisticLocking = !entityMetamodel.isVersioned()
|
final boolean isImpliedOptimisticLocking = !entityMetamodel.isVersioned()
|
||||||
&& entityMetamodel.getOptimisticLockStyle().isAllOrDirty();
|
&& entityMetamodel.getOptimisticLockStyle().isAllOrDirty();
|
||||||
if ( isImpliedOptimisticLocking && entry.getLoadedState() != null ) {
|
if ( isImpliedOptimisticLocking && entry.getLoadedState() != null ) {
|
||||||
// The entity will be deleted and because we are going to create a delete statement that uses
|
// The entity will be deleted and because we are going to create a delete statement
|
||||||
// all the state values in the where clause, the entry state needs to be updated otherwise the statement execution will
|
// that uses all the state values in the where clause, the entry state needs to be
|
||||||
// not delete any row (see HHH-15218).
|
// updated otherwise the statement execution will not delete any row (see HHH-15218).
|
||||||
entry.postUpdate( instance, state, nextVersion );
|
entry.postUpdate( instance, state, nextVersion );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final StatisticsImplementor statistics = factory.getStatistics();
|
|
||||||
if ( persister.canWriteToCache() ) {
|
|
||||||
if ( persister.isCacheInvalidationRequired() || entry.getStatus() != Status.MANAGED ) {
|
|
||||||
persister.getCacheAccessStrategy().remove( session, ck );
|
|
||||||
}
|
|
||||||
else if ( session.getCacheMode().isPutEnabled() ) {
|
|
||||||
//TODO: inefficient if that cache is just going to ignore the updated state!
|
|
||||||
final CacheEntry ce = persister.buildCacheEntry( instance, state, nextVersion, getSession() );
|
|
||||||
cacheEntry = persister.getCacheEntryStructure().structure( ce );
|
|
||||||
|
|
||||||
final boolean put = cacheUpdate( persister, previousVersion, ck );
|
|
||||||
if ( put && statistics.isStatisticsEnabled() ) {
|
|
||||||
statistics.entityCachePut(
|
|
||||||
StatsHelper.INSTANCE.getRootEntityRole( persister ),
|
|
||||||
getPersister().getCacheAccessStrategy().getRegion().getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( naturalIdMapping != null ) {
|
|
||||||
session.getPersistenceContextInternal().getNaturalIdResolutions().manageSharedResolution(
|
|
||||||
id,
|
|
||||||
naturalIdMapping.extractNaturalIdFromEntityState( state, session ),
|
|
||||||
previousNaturalIdValues,
|
|
||||||
persister,
|
|
||||||
CachedNaturalIdValueSource.UPDATE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
postUpdate();
|
|
||||||
|
|
||||||
if ( statistics.isStatisticsEnabled() ) {
|
|
||||||
statistics.updateEntity( getPersister().getEntityName() );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean cacheUpdate(EntityPersister persister, Object previousVersion, Object ck) {
|
private Object getPreviousVersion() {
|
||||||
|
final EntityPersister persister = getPersister();
|
||||||
|
if ( persister.isVersionPropertyGenerated() ) {
|
||||||
|
// we need to grab the version value from the entity, otherwise
|
||||||
|
// we have issues with generated-version entities that may have
|
||||||
|
// multiple actions queued during the same flush
|
||||||
|
return persister.getVersion( getInstance() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return previousVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object lockCacheItem(Object previousVersion) {
|
||||||
|
final EntityPersister persister = getPersister();
|
||||||
|
if ( persister.canWriteToCache() ) {
|
||||||
|
final SharedSessionContractImplementor session = getSession();
|
||||||
|
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||||
|
final Object ck = cache.generateCacheKey(
|
||||||
|
getId(),
|
||||||
|
persister,
|
||||||
|
session.getFactory(),
|
||||||
|
session.getTenantIdentifier()
|
||||||
|
);
|
||||||
|
lock = cache.lockItem( session, ck, previousVersion );
|
||||||
|
return ck;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean updateCache(EntityPersister persister, Object previousVersion, Object ck) {
|
||||||
final SharedSessionContractImplementor session = getSession();
|
final SharedSessionContractImplementor session = getSession();
|
||||||
try {
|
try {
|
||||||
session.getEventListenerManager().cachePutStart();
|
session.getEventListenerManager().cachePutStart();
|
||||||
|
@ -264,28 +273,30 @@ public class EntityUpdateAction extends EntityAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean preUpdate() {
|
protected boolean preUpdate() {
|
||||||
boolean veto = false;
|
final EventListenerGroup<PreUpdateEventListener> listenerGroup
|
||||||
final EventListenerGroup<PreUpdateEventListener> listenerGroup = getFastSessionServices().eventListenerGroup_PRE_UPDATE;
|
= getFastSessionServices().eventListenerGroup_PRE_UPDATE;
|
||||||
if ( listenerGroup.isEmpty() ) {
|
if ( listenerGroup.isEmpty() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final PreUpdateEvent event = new PreUpdateEvent(
|
||||||
|
getInstance(),
|
||||||
|
getId(),
|
||||||
|
state,
|
||||||
|
previousState,
|
||||||
|
getPersister(),
|
||||||
|
eventSource()
|
||||||
|
);
|
||||||
|
boolean veto = false;
|
||||||
|
for ( PreUpdateEventListener listener : listenerGroup.listeners() ) {
|
||||||
|
veto |= listener.onPreUpdate( event );
|
||||||
|
}
|
||||||
return veto;
|
return veto;
|
||||||
}
|
}
|
||||||
final PreUpdateEvent event = new PreUpdateEvent(
|
|
||||||
getInstance(),
|
|
||||||
getId(),
|
|
||||||
state,
|
|
||||||
previousState,
|
|
||||||
getPersister(),
|
|
||||||
eventSource()
|
|
||||||
);
|
|
||||||
for ( PreUpdateEventListener listener : listenerGroup.listeners() ) {
|
|
||||||
veto |= listener.onPreUpdate( event );
|
|
||||||
}
|
|
||||||
return veto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void postUpdate() {
|
protected void postUpdate() {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_POST_UPDATE
|
||||||
.eventListenerGroup_POST_UPDATE
|
|
||||||
.fireLazyEventOnEachListener( this::newPostUpdateEvent, PostUpdateEventListener::onPostUpdate );
|
.fireLazyEventOnEachListener( this::newPostUpdateEvent, PostUpdateEventListener::onPostUpdate );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,9 +313,9 @@ public class EntityUpdateAction extends EntityAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void postCommitUpdate(boolean success) {
|
protected void postCommitUpdate(boolean success) {
|
||||||
getFastSessionServices()
|
getFastSessionServices().eventListenerGroup_POST_COMMIT_UPDATE
|
||||||
.eventListenerGroup_POST_COMMIT_UPDATE
|
.fireLazyEventOnEachListener( this::newPostUpdateEvent,
|
||||||
.fireLazyEventOnEachListener( this::newPostUpdateEvent, success ? PostUpdateEventListener::onPostUpdate : this::onPostCommitFailure );
|
success ? PostUpdateEventListener::onPostUpdate : this::onPostCommitFailure );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPostCommitFailure(PostUpdateEventListener listener, PostUpdateEvent event) {
|
private void onPostCommitFailure(PostUpdateEventListener listener, PostUpdateEvent event) {
|
||||||
|
@ -319,18 +330,23 @@ public class EntityUpdateAction extends EntityAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasPostCommitEventListeners() {
|
protected boolean hasPostCommitEventListeners() {
|
||||||
final EventListenerGroup<PostUpdateEventListener> group = getFastSessionServices().eventListenerGroup_POST_COMMIT_UPDATE;
|
final EventListenerGroup<PostUpdateEventListener> group
|
||||||
|
= getFastSessionServices().eventListenerGroup_POST_COMMIT_UPDATE;
|
||||||
for ( PostUpdateEventListener listener : group.listeners() ) {
|
for ( PostUpdateEventListener listener : group.listeners() ) {
|
||||||
if ( listener.requiresPostCommitHandling( getPersister() ) ) {
|
if ( listener.requiresPostCommitHandling( getPersister() ) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws CacheException {
|
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws CacheException {
|
||||||
|
updateCacheIfNecessary( success, session );
|
||||||
|
postCommitUpdate( success );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCacheIfNecessary(boolean success, SharedSessionContractImplementor session) {
|
||||||
final EntityPersister persister = getPersister();
|
final EntityPersister persister = getPersister();
|
||||||
if ( persister.canWriteToCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||||
|
@ -342,38 +358,40 @@ public class EntityUpdateAction extends EntityAction {
|
||||||
session.getTenantIdentifier()
|
session.getTenantIdentifier()
|
||||||
|
|
||||||
);
|
);
|
||||||
|
if ( cacheUpdateRequired( success, persister, session ) ) {
|
||||||
if ( success &&
|
cacheAfterUpdate( cache, ck, session);
|
||||||
cacheEntry != null &&
|
|
||||||
!persister.isCacheInvalidationRequired() &&
|
|
||||||
session.getCacheMode().isPutEnabled() ) {
|
|
||||||
final boolean put = cacheAfterUpdate( cache, ck );
|
|
||||||
|
|
||||||
final StatisticsImplementor statistics = factory.getStatistics();
|
|
||||||
if ( put && statistics.isStatisticsEnabled() ) {
|
|
||||||
statistics.entityCachePut(
|
|
||||||
StatsHelper.INSTANCE.getRootEntityRole( persister ),
|
|
||||||
cache.getRegion().getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cache.unlockItem( session, ck, lock );
|
cache.unlockItem( session, ck, lock );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postCommitUpdate( success );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean cacheAfterUpdate(EntityDataAccess cache, Object ck) {
|
private boolean cacheUpdateRequired(boolean success, EntityPersister persister, SharedSessionContractImplementor session) {
|
||||||
final SharedSessionContractImplementor session = getSession();
|
return success
|
||||||
SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
|
&& cacheEntry != null
|
||||||
|
&& !persister.isCacheInvalidationRequired()
|
||||||
|
&& session.getCacheMode().isPutEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cacheAfterUpdate(EntityDataAccess cache, Object ck, SharedSessionContractImplementor session) {
|
||||||
|
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
|
||||||
try {
|
try {
|
||||||
eventListenerManager.cachePutStart();
|
eventListenerManager.cachePutStart();
|
||||||
return cache.afterUpdate( session, ck, cacheEntry, nextVersion, previousVersion, lock );
|
boolean put = cache.afterUpdate( session, ck, cacheEntry, nextVersion, previousVersion, lock );
|
||||||
|
|
||||||
|
final StatisticsImplementor statistics = session.getFactory().getStatistics();
|
||||||
|
if ( put && statistics.isStatisticsEnabled() ) {
|
||||||
|
statistics.entityCachePut(
|
||||||
|
StatsHelper.INSTANCE.getRootEntityRole( getPersister() ),
|
||||||
|
cache.getRegion().getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
eventListenerManager.cachePutEnd();
|
eventListenerManager.cachePutEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.pretty.MessageHelper;
|
||||||
* @author Scott Marlow
|
* @author Scott Marlow
|
||||||
*/
|
*/
|
||||||
public class EntityVerifyVersionProcess implements BeforeTransactionCompletionProcess {
|
public class EntityVerifyVersionProcess implements BeforeTransactionCompletionProcess {
|
||||||
|
|
||||||
private final Object object;
|
private final Object object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,19 +36,18 @@ public class EntityVerifyVersionProcess implements BeforeTransactionCompletionPr
|
||||||
public void doBeforeTransactionCompletion(SessionImplementor session) {
|
public void doBeforeTransactionCompletion(SessionImplementor session) {
|
||||||
final EntityEntry entry = session.getPersistenceContext().getEntry( object );
|
final EntityEntry entry = session.getPersistenceContext().getEntry( object );
|
||||||
// Don't check version for an entity that is not in the PersistenceContext;
|
// Don't check version for an entity that is not in the PersistenceContext;
|
||||||
if ( entry == null ) {
|
if ( entry != null ) {
|
||||||
return;
|
final Object latestVersion = entry.getPersister().getCurrentVersion( entry.getId(), session );
|
||||||
}
|
if ( !entry.getVersion().equals( latestVersion ) ) {
|
||||||
|
throw new OptimisticEntityLockException(
|
||||||
final EntityPersister persister = entry.getPersister();
|
object,
|
||||||
final Object latestVersion = persister.getCurrentVersion( entry.getId(), session );
|
"Newer version ["
|
||||||
if ( !entry.getVersion().equals( latestVersion ) ) {
|
+ latestVersion
|
||||||
throw new OptimisticEntityLockException(
|
+ "] of entity ["
|
||||||
object,
|
+ MessageHelper.infoString( entry.getEntityName(), entry.getId() )
|
||||||
"Newer version [" + latestVersion +
|
+ "] found in database"
|
||||||
"] of entity [" + MessageHelper.infoString( entry.getEntityName(), entry.getId() ) +
|
);
|
||||||
"] found in database"
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,6 @@ public class UnresolvedEntityInsertActions {
|
||||||
return dependenciesByAction.isEmpty();
|
return dependenciesByAction.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void addDependenciesByTransientEntity(AbstractEntityInsertAction insert, NonNullableTransientDependencies dependencies) {
|
private void addDependenciesByTransientEntity(AbstractEntityInsertAction insert, NonNullableTransientDependencies dependencies) {
|
||||||
for ( Object transientEntity : dependencies.getNonNullableTransientEntities() ) {
|
for ( Object transientEntity : dependencies.getNonNullableTransientEntities() ) {
|
||||||
Set<AbstractEntityInsertAction> dependentActions = dependentActionsByTransientEntity.get( transientEntity );
|
Set<AbstractEntityInsertAction> dependentActions = dependentActionsByTransientEntity.get( transientEntity );
|
||||||
|
@ -182,7 +181,6 @@ public class UnresolvedEntityInsertActions {
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException if {@code managedEntity} did not have managed or read-only status.
|
* @throws IllegalArgumentException if {@code managedEntity} did not have managed or read-only status.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Set<AbstractEntityInsertAction> resolveDependentActions(Object managedEntity, SessionImplementor session) {
|
public Set<AbstractEntityInsertAction> resolveDependentActions(Object managedEntity, SessionImplementor session) {
|
||||||
final EntityEntry entityEntry = session.getPersistenceContextInternal().getEntry( managedEntity );
|
final EntityEntry entityEntry = session.getPersistenceContextInternal().getEntry( managedEntity );
|
||||||
if ( entityEntry.getStatus() != Status.MANAGED && entityEntry.getStatus() != Status.READ_ONLY ) {
|
if ( entityEntry.getStatus() != Status.MANAGED && entityEntry.getStatus() != Status.READ_ONLY ) {
|
||||||
|
|
Loading…
Reference in New Issue