minor cleanups to Actions
This commit is contained in:
parent
8f8ae50e0b
commit
ee1d27719c
|
@ -34,13 +34,13 @@ import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
|||
import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||
|
||||
/**
|
||||
* An {@link org.hibernate.engine.spi.ActionQueue} {@link Executable} for ensuring
|
||||
* shared cache cleanup in relation to performed bulk HQL queries.
|
||||
* An {@link org.hibernate.engine.spi.ActionQueue} {@link Executable} for
|
||||
* ensuring shared cache cleanup in relation to performed bulk HQL queries.
|
||||
* <p/>
|
||||
* NOTE: currently this executes for {@code INSERT} queries as well as
|
||||
* {@code UPDATE} and {@code DELETE} queries. For {@code INSERT} it is
|
||||
* really not needed as we'd have no invalid entity/collection data to
|
||||
* cleanup (we'd still nee to invalidate the appropriate update-timestamps
|
||||
* clean up (we'd still need to invalidate the appropriate update-timestamps
|
||||
* regions) as a result of this query.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
|
@ -112,8 +112,7 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
|||
* @param session The session to which this request is tied.
|
||||
* @param tableSpaces The table spaces.
|
||||
*/
|
||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||
public BulkOperationCleanupAction(SharedSessionContractImplementor session, Set tableSpaces) {
|
||||
public BulkOperationCleanupAction(SharedSessionContractImplementor session, Set<String> tableSpaces) {
|
||||
final LinkedHashSet<String> spacesList = new LinkedHashSet<>( tableSpaces );
|
||||
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
|
|
|
@ -113,10 +113,10 @@ public abstract class CollectionAction implements Executable, Serializable, Comp
|
|||
if ( key instanceof DelayedPostInsertIdentifier ) {
|
||||
// need to look it up from the persistence-context
|
||||
finalKey = session.getPersistenceContextInternal().getEntry( collection.getOwner() ).getId();
|
||||
if ( finalKey == key ) {
|
||||
// if ( finalKey == key ) {
|
||||
// we may be screwed here since the collection action is about to execute
|
||||
// and we do not know the final owner key value
|
||||
}
|
||||
// }
|
||||
}
|
||||
return finalKey;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
|
|||
*/
|
||||
public final class CollectionRemoveAction extends CollectionAction {
|
||||
private final Object affectedOwner;
|
||||
private boolean emptySnapshot;
|
||||
private final boolean emptySnapshot;
|
||||
|
||||
/**
|
||||
* Removes a persistent collection from its loaded owner.
|
||||
|
|
|
@ -10,8 +10,6 @@ import org.hibernate.AssertionFailure;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.event.spi.PostCollectionUpdateEvent;
|
||||
import org.hibernate.event.spi.PostCollectionUpdateEventListener;
|
||||
import org.hibernate.event.spi.PreCollectionUpdateEvent;
|
||||
|
|
|
@ -12,23 +12,25 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
/**
|
||||
* Acts as a stand-in for an entity identifier which is supposed to be
|
||||
* generated on insert (like an IDENTITY column) where the insert needed to
|
||||
* be delayed because we were outside a transaction when the persist
|
||||
* occurred (save currently still performs the insert).
|
||||
* be delayed because we were outside a transaction when the persist operation
|
||||
* was called (save currently still performs the insert).
|
||||
* <p/>
|
||||
* The stand-in is only used within the {@link org.hibernate.engine.spi.PersistenceContext}
|
||||
* in order to distinguish one instance from another; it is never injected into
|
||||
* the entity instance or returned to the client...
|
||||
* the entity instance or returned to the client.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Sanne Grinovero
|
||||
*/
|
||||
public class DelayedPostInsertIdentifier implements Serializable, Comparable<DelayedPostInsertIdentifier> {
|
||||
public class DelayedPostInsertIdentifier
|
||||
implements Serializable, Comparable<DelayedPostInsertIdentifier> {
|
||||
|
||||
private static final AtomicLong SEQUENCE = new AtomicLong();
|
||||
|
||||
private final long identifier;
|
||||
|
||||
/**
|
||||
* Constructs a DelayedPostInsertIdentifier
|
||||
* Constructs a {@link DelayedPostInsertIdentifier}
|
||||
*/
|
||||
public DelayedPostInsertIdentifier() {
|
||||
long value = SEQUENCE.incrementAndGet();
|
||||
|
|
|
@ -14,10 +14,7 @@ import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
|
|||
import org.hibernate.action.spi.Executable;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.internal.FastSessionServices;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
@ -30,7 +27,7 @@ import org.hibernate.pretty.MessageHelper;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public abstract class EntityAction
|
||||
implements Executable, Serializable, Comparable, AfterTransactionCompletionProcess {
|
||||
implements Executable, Serializable, Comparable<EntityAction>, AfterTransactionCompletionProcess {
|
||||
|
||||
private final String entityName;
|
||||
private final Object id;
|
||||
|
@ -49,7 +46,11 @@ public abstract class EntityAction
|
|||
* @param instance The entity instance
|
||||
* @param persister The entity persister
|
||||
*/
|
||||
protected EntityAction(SharedSessionContractImplementor session, Object id, Object instance, EntityPersister persister) {
|
||||
protected EntityAction(
|
||||
SharedSessionContractImplementor session,
|
||||
Object id,
|
||||
Object instance,
|
||||
EntityPersister persister) {
|
||||
this.entityName = persister.getEntityName();
|
||||
this.id = id;
|
||||
this.instance = instance;
|
||||
|
@ -107,8 +108,8 @@ public abstract class EntityAction
|
|||
}
|
||||
|
||||
public final DelayedPostInsertIdentifier getDelayedId() {
|
||||
return DelayedPostInsertIdentifier.class.isInstance( id )
|
||||
? DelayedPostInsertIdentifier.class.cast( id )
|
||||
return id instanceof DelayedPostInsertIdentifier
|
||||
? (DelayedPostInsertIdentifier) id
|
||||
: null;
|
||||
}
|
||||
|
||||
|
@ -155,8 +156,7 @@ public abstract class EntityAction
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object other) {
|
||||
final EntityAction action = (EntityAction) other;
|
||||
public int compareTo(EntityAction action) {
|
||||
//sort first by entity name
|
||||
final int roleComparison = entityName.compareTo( action.entityName );
|
||||
if ( roleComparison != 0 ) {
|
||||
|
|
|
@ -34,7 +34,6 @@ public class EntityDeleteAction extends EntityAction {
|
|||
|
||||
private SoftLock lock;
|
||||
|
||||
private final NaturalIdMapping naturalIdMapping;
|
||||
private Object naturalIdValues;
|
||||
|
||||
/**
|
||||
|
@ -60,14 +59,15 @@ public class EntityDeleteAction extends EntityAction {
|
|||
this.isCascadeDeleteEnabled = isCascadeDeleteEnabled;
|
||||
this.state = state;
|
||||
|
||||
this.naturalIdMapping = persister.getNaturalIdMapping();
|
||||
NaturalIdMapping naturalIdMapping = persister.getNaturalIdMapping();
|
||||
|
||||
if ( naturalIdMapping != null ) {
|
||||
naturalIdValues = session.getPersistenceContextInternal().getNaturalIdResolutions().removeLocalResolution(
|
||||
getId(),
|
||||
naturalIdMapping.extractNaturalIdFromEntityState( state, session ),
|
||||
getPersister()
|
||||
);
|
||||
naturalIdValues = session.getPersistenceContextInternal().getNaturalIdResolutions()
|
||||
.removeLocalResolution(
|
||||
getId(),
|
||||
naturalIdMapping.extractNaturalIdFromEntityState( state, session ),
|
||||
getPersister()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ import org.hibernate.engine.spi.EntityKey;
|
|||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.event.spi.PostCommitInsertEventListener;
|
||||
import org.hibernate.event.spi.PostInsertEvent;
|
||||
import org.hibernate.event.spi.PostInsertEventListener;
|
||||
|
|
|
@ -12,8 +12,9 @@ import org.hibernate.engine.spi.SessionImplementor;
|
|||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
/**
|
||||
* A BeforeTransactionCompletionProcess impl to verify and increment an entity version as party
|
||||
* of before-transaction-completion processing
|
||||
* A {@link BeforeTransactionCompletionProcess} implementation to verify and
|
||||
* increment an entity version as party of before-transaction-completion
|
||||
* processing.
|
||||
*
|
||||
* @author Scott Marlow
|
||||
*/
|
||||
|
|
|
@ -18,7 +18,6 @@ import org.hibernate.engine.spi.SessionEventListenerManager;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.event.spi.PostCommitInsertEventListener;
|
||||
import org.hibernate.event.spi.PostInsertEvent;
|
||||
import org.hibernate.event.spi.PostInsertEventListener;
|
||||
|
|
|
@ -14,8 +14,8 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
import org.hibernate.pretty.MessageHelper;
|
||||
|
||||
/**
|
||||
* A BeforeTransactionCompletionProcess impl to verify an entity version as part of
|
||||
* before-transaction-completion processing
|
||||
* A {@link BeforeTransactionCompletionProcess} impl to verify an entity
|
||||
* version as part of before-transaction-completion processing.
|
||||
*
|
||||
* @author Scott Marlow
|
||||
*/
|
||||
|
|
|
@ -15,8 +15,10 @@ import org.hibernate.persister.collection.CollectionPersister;
|
|||
|
||||
/**
|
||||
* If a collection is extra lazy and has queued ops, we still need to
|
||||
* process them. Ex: OneToManyPersister needs to insert indexes for List
|
||||
* collections. See HHH-8083.
|
||||
* process them.
|
||||
* <p>
|
||||
* For example, {@link org.hibernate.persister.collection.OneToManyPersister}
|
||||
* needs to insert indexes for lists. See HHH-8083.
|
||||
*
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.hibernate.cache.CacheException;
|
|||
import org.hibernate.engine.internal.NonNullableTransientDependencies;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
|
@ -52,7 +53,6 @@ import org.hibernate.type.CollectionType;
|
|||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
import org.hibernate.type.OneToOneType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
|
@ -68,7 +68,7 @@ import org.hibernate.type.Type;
|
|||
public class ActionQueue {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( ActionQueue.class );
|
||||
|
||||
private SessionImplementor session;
|
||||
private final SessionImplementor session;
|
||||
|
||||
private UnresolvedEntityInsertActions unresolvedInsertions;
|
||||
|
||||
|
@ -103,7 +103,7 @@ public class ActionQueue {
|
|||
/**
|
||||
* A LinkedHashMap containing providers for all the ExecutableLists, inserted in execution order
|
||||
*/
|
||||
private static final LinkedHashMap<Class<? extends Executable>,ListProvider> EXECUTABLE_LISTS_MAP;
|
||||
private static final LinkedHashMap<Class<? extends Executable>,ListProvider<?>> EXECUTABLE_LISTS_MAP;
|
||||
static {
|
||||
EXECUTABLE_LISTS_MAP = CollectionHelper.linkedMapOfSize( 8 );
|
||||
|
||||
|
@ -302,9 +302,13 @@ public class ActionQueue {
|
|||
}
|
||||
}
|
||||
|
||||
private <T extends Executable & Comparable<? super T> & Serializable> void addAction(Class<T> executableClass, T action) {
|
||||
listProvider( executableClass ).getOrInit( this ).add( action );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Executable & Comparable & Serializable> void addAction(Class<T> executableClass, T action) {
|
||||
EXECUTABLE_LISTS_MAP.get( executableClass ).getOrInit( this ).add( action );
|
||||
private <T extends Executable & Comparable<? super T> & Serializable> ListProvider<T> listProvider(Class<T> actionClass) {
|
||||
return (ListProvider<T>) EXECUTABLE_LISTS_MAP.get(actionClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -533,7 +537,10 @@ public class ActionQueue {
|
|||
* @return {@code true} if insertions or deletions are currently queued; {@code false} otherwise.
|
||||
*/
|
||||
public boolean areInsertionsOrDeletionsQueued() {
|
||||
return ( insertions != null && !insertions.isEmpty() ) || hasUnresolvedEntityInsertActions() || (deletions != null && !deletions.isEmpty()) || (orphanRemovals != null && !orphanRemovals.isEmpty());
|
||||
return insertions != null && !insertions.isEmpty()
|
||||
|| hasUnresolvedEntityInsertActions()
|
||||
|| deletions != null && !deletions.isEmpty()
|
||||
|| orphanRemovals != null && !orphanRemovals.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -543,11 +550,11 @@ public class ActionQueue {
|
|||
*
|
||||
* @return {@code true} if we contain pending actions against any of the given tables; {@code false} otherwise.
|
||||
*/
|
||||
public boolean areTablesToBeUpdated(@SuppressWarnings("rawtypes") Set tables) {
|
||||
public boolean areTablesToBeUpdated(Set<Serializable> tables) {
|
||||
if ( tables.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
for ( ListProvider listProvider : EXECUTABLE_LISTS_MAP.values() ) {
|
||||
for ( ListProvider<?> listProvider : EXECUTABLE_LISTS_MAP.values() ) {
|
||||
ExecutableList<?> l = listProvider.get( this );
|
||||
if ( areTablesToBeUpdated( l, tables ) ) {
|
||||
return true;
|
||||
|
@ -559,7 +566,7 @@ public class ActionQueue {
|
|||
return areTablesToBeUpdated( unresolvedInsertions, tables );
|
||||
}
|
||||
|
||||
private static boolean areTablesToBeUpdated(ExecutableList<?> actions, @SuppressWarnings("rawtypes") Set tableSpaces) {
|
||||
private static boolean areTablesToBeUpdated(ExecutableList<?> actions, Set<Serializable> tableSpaces) {
|
||||
if ( actions == null || actions.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
|
@ -574,7 +581,7 @@ public class ActionQueue {
|
|||
return false;
|
||||
}
|
||||
|
||||
private static boolean areTablesToBeUpdated(UnresolvedEntityInsertActions actions, @SuppressWarnings("rawtypes") Set tableSpaces) {
|
||||
private static boolean areTablesToBeUpdated(UnresolvedEntityInsertActions actions, Set<Serializable> tableSpaces) {
|
||||
for ( Executable action : actions.getDependentEntityInsertActions() ) {
|
||||
final Serializable[] spaces = action.getPropertySpaces();
|
||||
for ( Serializable space : spaces ) {
|
||||
|
@ -593,7 +600,8 @@ public class ActionQueue {
|
|||
* @param list The list of Executable elements to be performed
|
||||
*
|
||||
*/
|
||||
private <E extends Executable & Comparable<?> & Serializable> void executeActions(ExecutableList<E> list) throws HibernateException {
|
||||
private <E extends Executable & Comparable<? super E> & Serializable> void executeActions(ExecutableList<E> list)
|
||||
throws HibernateException {
|
||||
// todo : consider ways to improve the double iteration of Executables here:
|
||||
// 1) we explicitly iterate list here to perform Executable#execute()
|
||||
// 2) ExecutableList#getQuerySpaces also iterates the Executables to collect query spaces.
|
||||
|
@ -632,8 +640,8 @@ public class ActionQueue {
|
|||
session.getJdbcCoordinator().executeBatch();
|
||||
}
|
||||
|
||||
private static String[] convertTimestampSpaces(Set spaces) {
|
||||
return (String[]) spaces.toArray( new String[ spaces.size() ] );
|
||||
private static String[] convertTimestampSpaces(Set<String> spaces) {
|
||||
return spaces.toArray(StringHelper.EMPTY_STRINGS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -655,11 +663,11 @@ public class ActionQueue {
|
|||
*/
|
||||
private void invalidateSpaces(String... spaces) {
|
||||
if ( spaces != null && spaces.length > 0 ) {
|
||||
for ( Serializable s : spaces ) {
|
||||
for ( String space : spaces ) {
|
||||
if ( afterTransactionProcesses == null ) {
|
||||
afterTransactionProcesses = new AfterTransactionCompletionProcessQueue( session );
|
||||
}
|
||||
afterTransactionProcesses.addSpaceToInvalidate( (String) s );
|
||||
afterTransactionProcesses.addSpaceToInvalidate( space );
|
||||
}
|
||||
// Performance win: If we are processing an ExecutableList, this will only be called once
|
||||
session.getFactory().getCache().getTimestampsCache().preInvalidate( spaces, session );
|
||||
|
@ -685,7 +693,7 @@ public class ActionQueue {
|
|||
+ "]";
|
||||
}
|
||||
|
||||
private static String toString(ExecutableList q) {
|
||||
private static String toString(ExecutableList<?> q) {
|
||||
return q == null ? "ExecutableList{size=0}" : q.toString();
|
||||
}
|
||||
|
||||
|
@ -748,7 +756,9 @@ public class ActionQueue {
|
|||
* @param processes Transaction completion processes.
|
||||
* @param isTransactionCoordinatorShared Flag indicating shared transaction context.
|
||||
*/
|
||||
public void setTransactionCompletionProcesses(TransactionCompletionProcesses processes, boolean isTransactionCoordinatorShared) {
|
||||
public void setTransactionCompletionProcesses(
|
||||
TransactionCompletionProcesses processes,
|
||||
boolean isTransactionCoordinatorShared) {
|
||||
this.isTransactionCoordinatorShared = isTransactionCoordinatorShared;
|
||||
this.beforeTransactionProcesses = processes.beforeTransactionCompletionProcesses;
|
||||
this.afterTransactionProcesses = processes.afterTransactionCompletionProcesses;
|
||||
|
@ -812,12 +822,14 @@ public class ActionQueue {
|
|||
|
||||
@SuppressWarnings("SimplifiableConditionalExpression")
|
||||
public boolean hasAfterTransactionActions() {
|
||||
return isTransactionCoordinatorShared ? false : afterTransactionProcesses != null && afterTransactionProcesses.hasActions();
|
||||
return isTransactionCoordinatorShared ? false
|
||||
: afterTransactionProcesses != null && afterTransactionProcesses.hasActions();
|
||||
}
|
||||
|
||||
@SuppressWarnings("SimplifiableConditionalExpression")
|
||||
public boolean hasBeforeTransactionActions() {
|
||||
return isTransactionCoordinatorShared ? false : beforeTransactionProcesses != null && beforeTransactionProcesses.hasActions();
|
||||
return isTransactionCoordinatorShared ? false
|
||||
: beforeTransactionProcesses != null && beforeTransactionProcesses.hasActions();
|
||||
}
|
||||
|
||||
public boolean hasAnyQueuedActions() {
|
||||
|
@ -868,7 +880,7 @@ public class ActionQueue {
|
|||
}
|
||||
unresolvedInsertions.serialize( oos );
|
||||
|
||||
for ( ListProvider p : EXECUTABLE_LISTS_MAP.values() ) {
|
||||
for ( ListProvider<?> p : EXECUTABLE_LISTS_MAP.values() ) {
|
||||
ExecutableList<?> l = p.get( this );
|
||||
if ( l == null ) {
|
||||
oos.writeBoolean( false );
|
||||
|
@ -889,7 +901,8 @@ public class ActionQueue {
|
|||
* @throws IOException indicates a problem reading from the stream
|
||||
* @throws ClassNotFoundException Generally means we were unable to locate user classes.
|
||||
*/
|
||||
public static ActionQueue deserialize(ObjectInputStream ois, SessionImplementor session) throws IOException, ClassNotFoundException {
|
||||
public static ActionQueue deserialize(ObjectInputStream ois, SessionImplementor session)
|
||||
throws IOException, ClassNotFoundException {
|
||||
final boolean traceEnabled = LOG.isTraceEnabled();
|
||||
if ( traceEnabled ) {
|
||||
LOG.trace( "Deserializing action-queue" );
|
||||
|
@ -898,7 +911,7 @@ public class ActionQueue {
|
|||
|
||||
rtn.unresolvedInsertions = UnresolvedEntityInsertActions.deserialize( ois, session );
|
||||
|
||||
for ( ListProvider provider : EXECUTABLE_LISTS_MAP.values() ) {
|
||||
for ( ListProvider<?> provider : EXECUTABLE_LISTS_MAP.values() ) {
|
||||
ExecutableList<?> l = provider.get( rtn );
|
||||
boolean notNull = ois.readBoolean();
|
||||
if ( notNull ) {
|
||||
|
@ -921,7 +934,7 @@ public class ActionQueue {
|
|||
protected SessionImplementor session;
|
||||
// Concurrency handling required when transaction completion process is dynamically registered
|
||||
// inside event listener (HHH-7478).
|
||||
protected Queue<T> processes = new ConcurrentLinkedQueue<T>();
|
||||
protected Queue<T> processes = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private AbstractTransactionCompletionProcessQueue(SessionImplementor session) {
|
||||
this.session = session;
|
||||
|
@ -965,8 +978,9 @@ public class ActionQueue {
|
|||
/**
|
||||
* Encapsulates behavior needed for after transaction processing
|
||||
*/
|
||||
private static class AfterTransactionCompletionProcessQueue extends AbstractTransactionCompletionProcessQueue<AfterTransactionCompletionProcess> {
|
||||
private Set<String> querySpacesToInvalidate = new HashSet<>();
|
||||
private static class AfterTransactionCompletionProcessQueue
|
||||
extends AbstractTransactionCompletionProcessQueue<AfterTransactionCompletionProcess> {
|
||||
private final Set<String> querySpacesToInvalidate = new HashSet<>();
|
||||
|
||||
private AfterTransactionCompletionProcessQueue(SessionImplementor session) {
|
||||
super( session );
|
||||
|
@ -992,7 +1006,7 @@ public class ActionQueue {
|
|||
|
||||
if ( session.getFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) {
|
||||
session.getFactory().getCache().getTimestampsCache().invalidate(
|
||||
querySpacesToInvalidate.toArray( new String[querySpacesToInvalidate.size()] ),
|
||||
querySpacesToInvalidate.toArray(StringHelper.EMPTY_STRINGS),
|
||||
session
|
||||
);
|
||||
}
|
||||
|
@ -1038,9 +1052,9 @@ public class ActionQueue {
|
|||
private final String entityName;
|
||||
private final String rootEntityName;
|
||||
|
||||
private Set<String> parentEntityNames = new HashSet<>( );
|
||||
private final Set<String> parentEntityNames = new HashSet<>( );
|
||||
|
||||
private Set<String> childEntityNames = new HashSet<>( );
|
||||
private final Set<String> childEntityNames = new HashSet<>( );
|
||||
|
||||
private BatchIdentifier parent;
|
||||
|
||||
|
@ -1111,7 +1125,8 @@ public class ActionQueue {
|
|||
return (
|
||||
parent == batchIdentifier
|
||||
|| parentEntityNames.contains( batchIdentifier.getEntityName() )
|
||||
|| ( parentEntityNames.contains( batchIdentifier.getRootEntityName() ) && !this.getEntityName().equals( batchIdentifier.getRootEntityName() ) )
|
||||
|| ( parentEntityNames.contains( batchIdentifier.getRootEntityName() )
|
||||
&& !this.getEntityName().equals( batchIdentifier.getRootEntityName() ) )
|
||||
|| parent != null && parent.hasParent( batchIdentifier, new ArrayList<>() )
|
||||
);
|
||||
}
|
||||
|
@ -1233,8 +1248,12 @@ public class ActionQueue {
|
|||
while ( !sorted && iterations <= maxIterations );
|
||||
|
||||
if ( iterations > maxIterations ) {
|
||||
LOG.warn( "The batch containing " + latestBatches.size() + " statements could not be sorted after " + maxIterations + " iterations. " +
|
||||
"This might indicate a circular entity relationship." );
|
||||
LOG.warn( "The batch containing "
|
||||
+ latestBatches.size()
|
||||
+ " statements could not be sorted after "
|
||||
+ maxIterations
|
||||
+ " iterations. "
|
||||
+ "This might indicate a circular entity relationship." );
|
||||
}
|
||||
|
||||
// Now, rebuild the insertions list. There is a batch for each entry in the name list.
|
||||
|
@ -1277,13 +1296,18 @@ public class ActionQueue {
|
|||
}
|
||||
}
|
||||
|
||||
private void addParentChildEntityNameByPropertyAndValue(AbstractEntityInsertAction action, BatchIdentifier batchIdentifier, Type type, Object value) {
|
||||
private void addParentChildEntityNameByPropertyAndValue(
|
||||
AbstractEntityInsertAction action,
|
||||
BatchIdentifier batchIdentifier,
|
||||
Type type,
|
||||
Object value) {
|
||||
if ( type.isEntityType() ) {
|
||||
final EntityType entityType = (EntityType) type;
|
||||
final String entityName = entityType.getName();
|
||||
final String rootEntityName = action.getSession().getFactory().getMetamodel().entityPersister( entityName ).getRootEntityName();
|
||||
final String rootEntityName = action.getSession().getFactory().getMetamodel().
|
||||
entityPersister( entityName ).getRootEntityName();
|
||||
|
||||
if ( entityType.isOneToOne() && OneToOneType.class.cast( entityType ).getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) {
|
||||
if ( entityType.isOneToOne() && entityType.getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) {
|
||||
if ( !entityType.isReferenceToPrimaryKey() ) {
|
||||
batchIdentifier.getChildEntityNames().add( entityName );
|
||||
}
|
||||
|
@ -1308,12 +1332,12 @@ public class ActionQueue {
|
|||
}
|
||||
else if ( type.isCollectionType() ) {
|
||||
CollectionType collectionType = (CollectionType) type;
|
||||
final SessionFactoryImplementor sessionFactory = ( (SessionImplementor) action.getSession() )
|
||||
.getSessionFactory();
|
||||
final SessionFactoryImplementor sessionFactory = action.getSession().getSessionFactory();
|
||||
if ( collectionType.getElementType( sessionFactory ).isEntityType() &&
|
||||
!sessionFactory.getMetamodel().collectionPersister( collectionType.getRole() ).isManyToMany() ) {
|
||||
String entityName = collectionType.getAssociatedEntityName( sessionFactory );
|
||||
String rootEntityName = action.getSession().getFactory().getMetamodel().entityPersister( entityName ).getRootEntityName();
|
||||
String rootEntityName = action.getSession().getFactory().getMetamodel()
|
||||
.entityPersister( entityName ).getRootEntityName();
|
||||
batchIdentifier.getChildEntityNames().add( entityName );
|
||||
if ( !rootEntityName.equals( entityName ) ) {
|
||||
batchIdentifier.getChildEntityNames().add( rootEntityName );
|
||||
|
@ -1345,7 +1369,7 @@ public class ActionQueue {
|
|||
|
||||
}
|
||||
|
||||
private abstract static class ListProvider<T extends Executable & Comparable & Serializable> {
|
||||
private abstract static class ListProvider<T extends Executable & Comparable<? super T> & Serializable> {
|
||||
abstract ExecutableList<T> get(ActionQueue instance);
|
||||
abstract ExecutableList<T> init(ActionQueue instance);
|
||||
ExecutableList<T> getOrInit( ActionQueue instance ) {
|
||||
|
|
|
@ -16,8 +16,8 @@ import java.io.Serializable;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public final class AssociationKey implements Serializable {
|
||||
private EntityKey ownerKey;
|
||||
private String propertyName;
|
||||
private final EntityKey ownerKey;
|
||||
private final String propertyName;
|
||||
|
||||
/**
|
||||
* Constructs an AssociationKey
|
||||
|
|
|
@ -22,29 +22,26 @@ import org.hibernate.action.spi.Executable;
|
|||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
|
||||
/**
|
||||
* Specialized encapsulating of the state pertaining to each Executable list.
|
||||
* <p/>
|
||||
* Manages sorting the executables (lazily)
|
||||
* <p/>
|
||||
* Manages the querySpaces affected by the executables in the list, and caches this too.
|
||||
* A list of {@link Executable executeble actions}. Responsible for
|
||||
* {@linkplain #sort() sorting} the executables, and calculating the
|
||||
* affected {@linkplain #getQuerySpaces() query spaces}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Anton Marsden
|
||||
*
|
||||
* @param <E> Intersection type describing Executable implementations
|
||||
* @param <E> Intersection type describing {@link Executable} implementations
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class ExecutableList<E extends Executable & Comparable & Serializable> implements Serializable, Iterable<E>, Externalizable {
|
||||
public class ExecutableList<E extends Executable & Comparable<? super E> & Serializable>
|
||||
implements Serializable, Iterable<E>, Externalizable {
|
||||
|
||||
public static final int INIT_QUEUE_LIST_SIZE = 5;
|
||||
|
||||
/**
|
||||
* Provides a sorting interface for ExecutableList.
|
||||
* Provides a sorting interface for {@link ExecutableList}.
|
||||
*
|
||||
* @param <E>
|
||||
*/
|
||||
public interface Sorter<E extends Executable> {
|
||||
|
||||
/**
|
||||
* Sorts the list.
|
||||
*/
|
||||
|
@ -58,22 +55,22 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
private boolean sorted;
|
||||
|
||||
/**
|
||||
* Used to hold the query spaces (table names, roughly) that all the Executable instances contained
|
||||
* in this list define. This information is ultimately used to invalidate cache regions as it is
|
||||
* exposed from {@link #getQuerySpaces}. This value being {@code null} indicates that the
|
||||
* query spaces should be calculated.
|
||||
* Used to hold the query spaces (table names, roughly) that all the {@link Executable}
|
||||
* instances contained in this list define. This information is ultimately used to
|
||||
* invalidate cache regions as it is exposed from {@link #getQuerySpaces}. This value
|
||||
* being {@code null} indicates that the query spaces should be calculated.
|
||||
*/
|
||||
private transient Set<Serializable> querySpaces;
|
||||
|
||||
/**
|
||||
* Creates a new ExecutableList with the default settings.
|
||||
* Creates a new instance with the default settings.
|
||||
*/
|
||||
public ExecutableList() {
|
||||
this( INIT_QUEUE_LIST_SIZE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExecutableList with the specified initialCapacity.
|
||||
* Creates a new instance with the given initial capacity.
|
||||
*
|
||||
* @param initialCapacity The initial capacity for instantiating the internal List
|
||||
*/
|
||||
|
@ -95,7 +92,7 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExecutableList using the specified Sorter.
|
||||
* Creates a new instance using the given {@link Sorter}.
|
||||
*
|
||||
* @param sorter The Sorter to use; may be {@code null}
|
||||
*/
|
||||
|
@ -104,7 +101,7 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExecutableList with the specified initialCapacity and Sorter.
|
||||
* Creates a new instance with the given initial capacity and {@link Sorter}.
|
||||
*
|
||||
* @param initialCapacity The initial capacity for instantiating the internal List
|
||||
* @param sorter The Sorter to use; may be {@code null}
|
||||
|
@ -156,7 +153,7 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
* @return the entry that was removed
|
||||
*/
|
||||
public E remove(int index) {
|
||||
// removals are generally safe in regards to sorting...
|
||||
// removals are generally safe with regard to sorting...
|
||||
|
||||
final E e = executables.remove( index );
|
||||
|
||||
|
@ -201,7 +198,7 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
}
|
||||
|
||||
/**
|
||||
* Add an Executable to this list.
|
||||
* Add an {@link Executable} to this list.
|
||||
*
|
||||
* @param executable the executable to add to the list
|
||||
*
|
||||
|
@ -235,13 +232,13 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
Collections.addAll( this.querySpaces, querySpaces );
|
||||
}
|
||||
|
||||
return added;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the list using the natural ordering or using the Sorter if it's not null.
|
||||
* Sorts the list using the natural ordering or using the {@link Sorter}
|
||||
* if it's not null.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void sort() {
|
||||
if ( sorted || !requiresSorting ) {
|
||||
// nothing to do
|
||||
|
@ -311,12 +308,12 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
}
|
||||
|
||||
/**
|
||||
* Read this object state back in from the given stream as part of de-serialization
|
||||
* Read this object state back in from the given stream as part of
|
||||
* the deserialization process.
|
||||
*
|
||||
* @param in The stream from which to read our serial state
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
sorted = in.readBoolean();
|
||||
|
||||
|
@ -324,6 +321,7 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
executables.ensureCapacity( numberOfExecutables );
|
||||
if ( numberOfExecutables > 0 ) {
|
||||
for ( int i = 0; i < numberOfExecutables; i++ ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
E e = (E) in.readObject();
|
||||
executables.add( e );
|
||||
}
|
||||
|
@ -342,9 +340,10 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
}
|
||||
|
||||
/**
|
||||
* Allow the Executables to re-associate themselves with the Session after deserialization.
|
||||
* Allow the {@link Executable}s to reassociate themselves with the
|
||||
* session after deserialization.
|
||||
*
|
||||
* @param session The session to which to associate the Executables
|
||||
* @param session The session with which to associate the {@code Executable}s
|
||||
*/
|
||||
public void afterDeserialize(SessionImplementor session) {
|
||||
for ( E e : executables ) {
|
||||
|
|
|
@ -67,7 +67,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
|
|||
*
|
||||
*/
|
||||
public void onDelete(DeleteEvent event) throws HibernateException {
|
||||
onDelete( event, new IdentitySet() );
|
||||
onDelete( event, new IdentitySet<>() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -281,7 +281,8 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
|
|||
persistenceContext.registerNullifiableEntityKey( key );
|
||||
|
||||
if ( isOrphanRemovalBeforeUpdates ) {
|
||||
// TODO: The removeOrphan concept is a temporary "hack" for HHH-6484. This should be removed once action/task
|
||||
// TODO: The removeOrphan concept is a temporary "hack" for HHH-6484.
|
||||
// This should be removed once action/task
|
||||
// ordering is improved.
|
||||
session.getActionQueue().addAction(
|
||||
new OrphanRemovalAction(
|
||||
|
|
Loading…
Reference in New Issue