HHH-10279 - Memory usage improvements -
* Don't allocate IdentityMap if it is not needed
* Only allocate unresolved insertions if requied
* Don't create a new string when creating a named query
* Allocate querySpaces lazily
* Remove executableLists from ActionQueue
* Allocate ExecutableList instances lazily
* Lazily allocate the transaction commit task lists
* Don't allocate a new EntityKey
(cherry picked from commit 991ff265da
)
This commit is contained in:
parent
38c355ed42
commit
feacc4a3b0
|
@ -213,7 +213,12 @@ public class HQLQueryPlan implements Serializable {
|
|||
|
||||
final int guessedResultSize = guessResultSize( rowSelection );
|
||||
final List combinedResults = new ArrayList( guessedResultSize );
|
||||
final IdentitySet distinction = new IdentitySet( guessedResultSize );
|
||||
final IdentitySet distinction;
|
||||
if ( needsLimit ) {
|
||||
distinction = new IdentitySet(guessedResultSize);
|
||||
} else {
|
||||
distinction = null;
|
||||
}
|
||||
int includedCount = -1;
|
||||
translator_loop:
|
||||
for ( QueryTranslator translator : translators ) {
|
||||
|
|
|
@ -10,8 +10,6 @@ import java.io.IOException;
|
|||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
|
@ -67,30 +65,61 @@ public class ActionQueue {
|
|||
// Object insertions, updates, and deletions have list semantics because
|
||||
// they must happen in the right order so as to respect referential
|
||||
// integrity
|
||||
private final ExecutableList<AbstractEntityInsertAction> insertions;
|
||||
private final ExecutableList<EntityDeleteAction> deletions;
|
||||
private final ExecutableList<EntityUpdateAction> updates;
|
||||
private ExecutableList<AbstractEntityInsertAction> insertions;
|
||||
private ExecutableList<EntityDeleteAction> deletions;
|
||||
private ExecutableList<EntityUpdateAction> updates;
|
||||
|
||||
// Actually the semantics of the next three are really "Bag"
|
||||
// Note that, unlike objects, collection insertions, updates,
|
||||
// deletions are not really remembered between flushes. We
|
||||
// just re-use the same Lists for convenience.
|
||||
private final ExecutableList<CollectionRecreateAction> collectionCreations;
|
||||
private final ExecutableList<CollectionUpdateAction> collectionUpdates;
|
||||
private final ExecutableList<QueuedOperationCollectionAction> collectionQueuedOps;
|
||||
private final ExecutableList<CollectionRemoveAction> collectionRemovals;
|
||||
private ExecutableList<CollectionRecreateAction> collectionCreations;
|
||||
private ExecutableList<CollectionUpdateAction> collectionUpdates;
|
||||
private ExecutableList<QueuedOperationCollectionAction> collectionQueuedOps;
|
||||
private ExecutableList<CollectionRemoveAction> collectionRemovals;
|
||||
|
||||
// TODO: The removeOrphan concept is a temporary "hack" for HHH-6484. This should be removed once action/task
|
||||
// ordering is improved.
|
||||
private final ExecutableList<OrphanRemovalAction> orphanRemovals;
|
||||
private ExecutableList<OrphanRemovalAction> orphanRemovals;
|
||||
|
||||
// an immutable array holding all 7 ExecutionLists in execution order
|
||||
private final List<ExecutableList<?>> executableLists;
|
||||
|
||||
private transient boolean isTransactionCoordinatorShared;
|
||||
private AfterTransactionCompletionProcessQueue afterTransactionProcesses;
|
||||
private BeforeTransactionCompletionProcessQueue beforeTransactionProcesses;
|
||||
|
||||
/**
|
||||
* An array containing providers for all the ExecutableLists in execution order
|
||||
*/
|
||||
private static final ListProvider[] EXECUTABLE_LISTS;
|
||||
|
||||
static {
|
||||
EXECUTABLE_LISTS = new ListProvider[8];
|
||||
EXECUTABLE_LISTS[0] = new ListProvider() {
|
||||
ExecutableList<?> get(ActionQueue instance) { return instance.orphanRemovals; }
|
||||
ExecutableList<?> init(ActionQueue instance) { return instance.orphanRemovals = new ExecutableList<OrphanRemovalAction>();} };
|
||||
EXECUTABLE_LISTS[1] = new ListProvider() {
|
||||
ExecutableList<?> get(ActionQueue instance) { return instance.insertions; }
|
||||
ExecutableList<?> init(ActionQueue instance) { return instance.insertions = new ExecutableList<AbstractEntityInsertAction>( new InsertActionSorter() );} };
|
||||
EXECUTABLE_LISTS[2] = new ListProvider() {
|
||||
ExecutableList<?> get(ActionQueue instance) { return instance.updates; }
|
||||
ExecutableList<?> init(ActionQueue instance) { return instance.updates = new ExecutableList<EntityUpdateAction>();} };
|
||||
EXECUTABLE_LISTS[3] = new ListProvider() {
|
||||
ExecutableList<?> get(ActionQueue instance) { return instance.collectionQueuedOps; }
|
||||
ExecutableList<?> init(ActionQueue instance) { return instance.collectionQueuedOps = new ExecutableList<QueuedOperationCollectionAction>();} };
|
||||
EXECUTABLE_LISTS[4] = new ListProvider() {
|
||||
ExecutableList<?> get(ActionQueue instance) { return instance.collectionRemovals; }
|
||||
ExecutableList<?> init(ActionQueue instance) { return instance.collectionRemovals = new ExecutableList<CollectionRemoveAction>();} };
|
||||
EXECUTABLE_LISTS[5] = new ListProvider() {
|
||||
ExecutableList<?> get(ActionQueue instance) { return instance.collectionUpdates; }
|
||||
ExecutableList<?> init(ActionQueue instance) { return instance.collectionUpdates = new ExecutableList<CollectionUpdateAction>();} };
|
||||
EXECUTABLE_LISTS[6] = new ListProvider() {
|
||||
ExecutableList<?> get(ActionQueue instance) { return instance.collectionCreations; }
|
||||
ExecutableList<?> init(ActionQueue instance) { return instance.collectionCreations = new ExecutableList<CollectionRecreateAction>();} };
|
||||
EXECUTABLE_LISTS[7] = new ListProvider() {
|
||||
ExecutableList<?> get(ActionQueue instance) { return instance.deletions; }
|
||||
ExecutableList<?> init(ActionQueue instance) { return instance.deletions = new ExecutableList<EntityDeleteAction>();} };
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an action queue bound to the given session.
|
||||
*
|
||||
|
@ -98,46 +127,19 @@ public class ActionQueue {
|
|||
*/
|
||||
public ActionQueue(SessionImplementor session) {
|
||||
this.session = session;
|
||||
|
||||
unresolvedInsertions = new UnresolvedEntityInsertActions();
|
||||
|
||||
insertions = new ExecutableList<AbstractEntityInsertAction>( new InsertActionSorter() );
|
||||
deletions = new ExecutableList<EntityDeleteAction>();
|
||||
updates = new ExecutableList<EntityUpdateAction>();
|
||||
|
||||
collectionCreations = new ExecutableList<CollectionRecreateAction>();
|
||||
collectionRemovals = new ExecutableList<CollectionRemoveAction>();
|
||||
collectionUpdates = new ExecutableList<CollectionUpdateAction>();
|
||||
collectionQueuedOps = new ExecutableList<QueuedOperationCollectionAction>();
|
||||
|
||||
orphanRemovals = new ExecutableList<OrphanRemovalAction>();
|
||||
|
||||
// Important: these lists are in execution order
|
||||
List<ExecutableList<?>> tmp = Arrays.<ExecutableList<?>>asList(
|
||||
orphanRemovals,
|
||||
insertions,
|
||||
updates,
|
||||
// do before actions are handled in the other collection queues
|
||||
collectionQueuedOps,
|
||||
collectionRemovals,
|
||||
collectionUpdates,
|
||||
collectionCreations,
|
||||
deletions
|
||||
);
|
||||
|
||||
executableLists = Collections.unmodifiableList( tmp );
|
||||
|
||||
isTransactionCoordinatorShared = false;
|
||||
afterTransactionProcesses = new AfterTransactionCompletionProcessQueue( session );
|
||||
beforeTransactionProcesses = new BeforeTransactionCompletionProcessQueue( session );
|
||||
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
for ( ExecutableList<?> l : executableLists ) {
|
||||
l.clear();
|
||||
for ( int i = 0; i < EXECUTABLE_LISTS.length; ++i ) {
|
||||
ExecutableList<?> l = EXECUTABLE_LISTS[i].get(this);
|
||||
if( l != null ) {
|
||||
l.clear();
|
||||
}
|
||||
}
|
||||
if( unresolvedInsertions != null ) {
|
||||
unresolvedInsertions.clear();
|
||||
}
|
||||
unresolvedInsertions.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,6 +169,9 @@ public class ActionQueue {
|
|||
LOG.tracev( "Adding insert with non-nullable, transient entities; insert=[{0}], dependencies=[{1}]", insert,
|
||||
nonNullableTransientDependencies.toLoggableString( insert.getSession() ) );
|
||||
}
|
||||
if( unresolvedInsertions == null ) {
|
||||
unresolvedInsertions = new UnresolvedEntityInsertActions();
|
||||
}
|
||||
unresolvedInsertions.addUnresolvedEntityInsertAction( insert, nonNullableTransientDependencies );
|
||||
}
|
||||
}
|
||||
|
@ -180,11 +185,16 @@ public class ActionQueue {
|
|||
}
|
||||
else {
|
||||
LOG.trace( "Adding resolved non-early insert action." );
|
||||
insertions.add( insert );
|
||||
if( insertions == null ) {
|
||||
insertions = new ExecutableList<AbstractEntityInsertAction>( new InsertActionSorter() );
|
||||
}
|
||||
insertions.add(insert);
|
||||
}
|
||||
insert.makeEntityManaged();
|
||||
for ( AbstractEntityInsertAction resolvedAction : unresolvedInsertions.resolveDependentActions( insert.getInstance(), session ) ) {
|
||||
addResolvedEntityInsertAction( resolvedAction );
|
||||
if( unresolvedInsertions != null ) {
|
||||
for (AbstractEntityInsertAction resolvedAction : unresolvedInsertions.resolveDependentActions(insert.getInstance(), session)) {
|
||||
addResolvedEntityInsertAction(resolvedAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,6 +214,9 @@ public class ActionQueue {
|
|||
* @param action The action representing the entity deletion
|
||||
*/
|
||||
public void addAction(EntityDeleteAction action) {
|
||||
if( deletions == null ) {
|
||||
deletions = new ExecutableList<EntityDeleteAction>();
|
||||
}
|
||||
deletions.add( action );
|
||||
}
|
||||
|
||||
|
@ -213,6 +226,9 @@ public class ActionQueue {
|
|||
* @param action The action representing the orphan removal
|
||||
*/
|
||||
public void addAction(OrphanRemovalAction action) {
|
||||
if( orphanRemovals == null ) {
|
||||
orphanRemovals = new ExecutableList<OrphanRemovalAction>();
|
||||
}
|
||||
orphanRemovals.add( action );
|
||||
}
|
||||
|
||||
|
@ -222,6 +238,9 @@ public class ActionQueue {
|
|||
* @param action The action representing the entity update
|
||||
*/
|
||||
public void addAction(EntityUpdateAction action) {
|
||||
if( updates == null ) {
|
||||
updates = new ExecutableList<EntityUpdateAction>();
|
||||
}
|
||||
updates.add( action );
|
||||
}
|
||||
|
||||
|
@ -231,6 +250,9 @@ public class ActionQueue {
|
|||
* @param action The action representing the (re)creation of a collection
|
||||
*/
|
||||
public void addAction(CollectionRecreateAction action) {
|
||||
if( collectionCreations == null) {
|
||||
collectionCreations = new ExecutableList<CollectionRecreateAction>();
|
||||
}
|
||||
collectionCreations.add( action );
|
||||
}
|
||||
|
||||
|
@ -240,6 +262,9 @@ public class ActionQueue {
|
|||
* @param action The action representing the removal of a collection
|
||||
*/
|
||||
public void addAction(CollectionRemoveAction action) {
|
||||
if( collectionRemovals == null ) {
|
||||
collectionRemovals = new ExecutableList<CollectionRemoveAction>();
|
||||
}
|
||||
collectionRemovals.add( action );
|
||||
}
|
||||
|
||||
|
@ -249,6 +274,9 @@ public class ActionQueue {
|
|||
* @param action The action representing the update of a collection
|
||||
*/
|
||||
public void addAction(CollectionUpdateAction action) {
|
||||
if( collectionUpdates == null ) {
|
||||
collectionUpdates = new ExecutableList<CollectionUpdateAction>();
|
||||
}
|
||||
collectionUpdates.add( action );
|
||||
}
|
||||
|
||||
|
@ -258,6 +286,9 @@ public class ActionQueue {
|
|||
* @param action The action representing the queued operation
|
||||
*/
|
||||
public void addAction(QueuedOperationCollectionAction action) {
|
||||
if( collectionQueuedOps == null) {
|
||||
collectionQueuedOps = new ExecutableList<QueuedOperationCollectionAction>();
|
||||
}
|
||||
collectionQueuedOps.add( action );
|
||||
}
|
||||
|
||||
|
@ -271,11 +302,21 @@ public class ActionQueue {
|
|||
}
|
||||
|
||||
private void registerCleanupActions(Executable executable) {
|
||||
beforeTransactionProcesses.register( executable.getBeforeTransactionCompletionProcess() );
|
||||
if( executable.getBeforeTransactionCompletionProcess() != null ) {
|
||||
if( beforeTransactionProcesses == null ) {
|
||||
beforeTransactionProcesses = new BeforeTransactionCompletionProcessQueue( session );
|
||||
}
|
||||
beforeTransactionProcesses.register(executable.getBeforeTransactionCompletionProcess());
|
||||
}
|
||||
if ( session.getFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) {
|
||||
invalidateSpaces( executable.getPropertySpaces() );
|
||||
}
|
||||
afterTransactionProcesses.register( executable.getAfterTransactionCompletionProcess() );
|
||||
if( executable.getAfterTransactionCompletionProcess() != null ) {
|
||||
if( afterTransactionProcesses == null ) {
|
||||
afterTransactionProcesses = new AfterTransactionCompletionProcessQueue( session );
|
||||
}
|
||||
afterTransactionProcesses.register(executable.getAfterTransactionCompletionProcess());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -285,7 +326,7 @@ public class ActionQueue {
|
|||
* transient entity; false, otherwise
|
||||
*/
|
||||
public boolean hasUnresolvedEntityInsertActions() {
|
||||
return !unresolvedInsertions.isEmpty();
|
||||
return unresolvedInsertions != null && !unresolvedInsertions.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -299,14 +340,22 @@ public class ActionQueue {
|
|||
* the first unresolved entity insert action.
|
||||
*/
|
||||
public void checkNoUnresolvedActionsAfterOperation() throws PropertyValueException {
|
||||
unresolvedInsertions.checkNoUnresolvedActionsAfterOperation();
|
||||
if(unresolvedInsertions != null) {
|
||||
unresolvedInsertions.checkNoUnresolvedActionsAfterOperation();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerProcess(AfterTransactionCompletionProcess process) {
|
||||
if( afterTransactionProcesses == null ) {
|
||||
afterTransactionProcesses = new AfterTransactionCompletionProcessQueue( session );
|
||||
}
|
||||
afterTransactionProcesses.register( process );
|
||||
}
|
||||
|
||||
public void registerProcess(BeforeTransactionCompletionProcess process) {
|
||||
if( beforeTransactionProcesses == null ) {
|
||||
beforeTransactionProcesses = new BeforeTransactionCompletionProcessQueue( session );
|
||||
}
|
||||
beforeTransactionProcesses.register( process );
|
||||
}
|
||||
|
||||
|
@ -316,7 +365,7 @@ public class ActionQueue {
|
|||
* @throws HibernateException error executing queued insertion actions.
|
||||
*/
|
||||
public void executeInserts() throws HibernateException {
|
||||
if ( !insertions.isEmpty() ) {
|
||||
if ( insertions != null && !insertions.isEmpty() ) {
|
||||
executeActions( insertions );
|
||||
}
|
||||
}
|
||||
|
@ -327,12 +376,13 @@ public class ActionQueue {
|
|||
* @throws HibernateException error executing queued actions.
|
||||
*/
|
||||
public void executeActions() throws HibernateException {
|
||||
if ( !unresolvedInsertions.isEmpty() ) {
|
||||
if ( hasUnresolvedEntityInsertActions() ) {
|
||||
throw new IllegalStateException( "About to execute actions, but there are unresolved entity insert actions." );
|
||||
}
|
||||
|
||||
for ( ExecutableList<?> l : executableLists ) {
|
||||
if ( !l.isEmpty() ) {
|
||||
for ( int i = 0; i < EXECUTABLE_LISTS.length; ++i ) {
|
||||
ExecutableList<?> l = EXECUTABLE_LISTS[i].get(this);
|
||||
if ( l != null && !l.isEmpty() ) {
|
||||
executeActions( l );
|
||||
}
|
||||
}
|
||||
|
@ -351,6 +401,9 @@ public class ActionQueue {
|
|||
}
|
||||
|
||||
private void prepareActions(ExecutableList<?> queue) throws HibernateException {
|
||||
if( queue == null ) {
|
||||
return;
|
||||
}
|
||||
for ( Executable executable : queue ) {
|
||||
executable.beforeExecutions();
|
||||
}
|
||||
|
@ -364,7 +417,9 @@ public class ActionQueue {
|
|||
public void afterTransactionCompletion(boolean success) {
|
||||
if ( !isTransactionCoordinatorShared ) {
|
||||
// Execute completion actions only in transaction owner (aka parent session).
|
||||
afterTransactionProcesses.afterTransactionCompletion( success );
|
||||
if( afterTransactionProcesses != null ) {
|
||||
afterTransactionProcesses.afterTransactionCompletion(success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -374,7 +429,9 @@ public class ActionQueue {
|
|||
public void beforeTransactionCompletion() {
|
||||
if ( !isTransactionCoordinatorShared ) {
|
||||
// Execute completion actions only in transaction owner (aka parent session).
|
||||
beforeTransactionProcesses.beforeTransactionCompletion();
|
||||
if( beforeTransactionProcesses != null ) {
|
||||
beforeTransactionProcesses.beforeTransactionCompletion();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,7 +441,7 @@ public class ActionQueue {
|
|||
* @return {@code true} if insertions or deletions are currently queued; {@code false} otherwise.
|
||||
*/
|
||||
public boolean areInsertionsOrDeletionsQueued() {
|
||||
return !insertions.isEmpty() || !unresolvedInsertions.isEmpty() || !deletions.isEmpty() || !orphanRemovals.isEmpty();
|
||||
return ( insertions != null && !insertions.isEmpty() ) || hasUnresolvedEntityInsertActions() || (deletions != null && !deletions.isEmpty()) || (orphanRemovals != null && !orphanRemovals.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -398,16 +455,20 @@ public class ActionQueue {
|
|||
if ( tables.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
for ( ExecutableList<?> l : executableLists ) {
|
||||
if ( areTablesToBeUpdated( l, tables ) ) {
|
||||
for ( int i = 0; i < EXECUTABLE_LISTS.length; ++i ) {
|
||||
ExecutableList<?> l = EXECUTABLE_LISTS[i].get(this);
|
||||
if ( areTablesToBeUpdated(l, tables) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(unresolvedInsertions == null) {
|
||||
return false;
|
||||
}
|
||||
return areTablesToBeUpdated( unresolvedInsertions, tables );
|
||||
}
|
||||
|
||||
private static boolean areTablesToBeUpdated(ExecutableList<?> actions, @SuppressWarnings("rawtypes") Set tableSpaces) {
|
||||
if ( actions.isEmpty() ) {
|
||||
if ( actions == null || actions.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -451,8 +512,18 @@ public class ActionQueue {
|
|||
e.execute();
|
||||
}
|
||||
finally {
|
||||
beforeTransactionProcesses.register( e.getBeforeTransactionCompletionProcess() );
|
||||
afterTransactionProcesses.register( e.getAfterTransactionCompletionProcess() );
|
||||
if( e.getBeforeTransactionCompletionProcess() != null ) {
|
||||
if( beforeTransactionProcesses == null ) {
|
||||
beforeTransactionProcesses = new BeforeTransactionCompletionProcessQueue( session );
|
||||
}
|
||||
beforeTransactionProcesses.register(e.getBeforeTransactionCompletionProcess());
|
||||
}
|
||||
if( e.getAfterTransactionCompletionProcess() != null ) {
|
||||
if( afterTransactionProcesses == null ) {
|
||||
afterTransactionProcesses = new AfterTransactionCompletionProcessQueue( session );
|
||||
}
|
||||
afterTransactionProcesses.register(e.getAfterTransactionCompletionProcess());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -490,6 +561,9 @@ public class ActionQueue {
|
|||
private void invalidateSpaces(Serializable... spaces) {
|
||||
if ( spaces != null && spaces.length > 0 ) {
|
||||
for ( Serializable s : spaces ) {
|
||||
if( afterTransactionProcesses == null ) {
|
||||
afterTransactionProcesses = new AfterTransactionCompletionProcessQueue( session );
|
||||
}
|
||||
afterTransactionProcesses.addSpaceToInvalidate( (String) s );
|
||||
}
|
||||
// Performance win: If we are processing an ExecutableList, this will only be called once
|
||||
|
@ -504,43 +578,70 @@ public class ActionQueue {
|
|||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ActionQueue[insertions=" + insertions
|
||||
+ " updates=" + updates
|
||||
+ " deletions=" + deletions
|
||||
+ " orphanRemovals=" + orphanRemovals
|
||||
+ " collectionCreations=" + collectionCreations
|
||||
+ " collectionRemovals=" + collectionRemovals
|
||||
+ " collectionUpdates=" + collectionUpdates
|
||||
+ " collectionQueuedOps=" + collectionQueuedOps
|
||||
return "ActionQueue[insertions=" + toString(insertions)
|
||||
+ " updates=" + toString(updates)
|
||||
+ " deletions=" + toString(deletions)
|
||||
+ " orphanRemovals=" + toString(orphanRemovals)
|
||||
+ " collectionCreations=" + toString(collectionCreations)
|
||||
+ " collectionRemovals=" + toString(collectionRemovals)
|
||||
+ " collectionUpdates=" + toString(collectionUpdates)
|
||||
+ " collectionQueuedOps=" + toString(collectionQueuedOps)
|
||||
+ " unresolvedInsertDependencies=" + unresolvedInsertions
|
||||
+ "]";
|
||||
}
|
||||
|
||||
private static String toString(ExecutableList q) {
|
||||
return q == null ? "ExecutableList{size=0}" : q.toString();
|
||||
}
|
||||
|
||||
public int numberOfCollectionRemovals() {
|
||||
if( collectionRemovals == null ) {
|
||||
return 0;
|
||||
}
|
||||
return collectionRemovals.size();
|
||||
}
|
||||
|
||||
public int numberOfCollectionUpdates() {
|
||||
if( collectionUpdates == null ) {
|
||||
return 0;
|
||||
}
|
||||
return collectionUpdates.size();
|
||||
}
|
||||
|
||||
public int numberOfCollectionCreations() {
|
||||
if( collectionCreations == null ) {
|
||||
return 0;
|
||||
}
|
||||
return collectionCreations.size();
|
||||
}
|
||||
|
||||
public int numberOfDeletions() {
|
||||
return deletions.size() + orphanRemovals.size();
|
||||
int del = deletions == null ? 0 : deletions.size();
|
||||
int orph = orphanRemovals == null ? 0 : orphanRemovals.size();
|
||||
return del + orph;
|
||||
}
|
||||
|
||||
public int numberOfUpdates() {
|
||||
if( updates == null ) {
|
||||
return 0;
|
||||
}
|
||||
return updates.size();
|
||||
}
|
||||
|
||||
public int numberOfInsertions() {
|
||||
if( insertions == null ) {
|
||||
return 0;
|
||||
}
|
||||
return insertions.size();
|
||||
}
|
||||
|
||||
public TransactionCompletionProcesses getTransactionCompletionProcesses() {
|
||||
if( beforeTransactionProcesses == null ) {
|
||||
beforeTransactionProcesses = new BeforeTransactionCompletionProcessQueue( session );
|
||||
}
|
||||
if( afterTransactionProcesses == null ) {
|
||||
afterTransactionProcesses = new AfterTransactionCompletionProcessQueue( session );
|
||||
}
|
||||
return new TransactionCompletionProcesses( beforeTransactionProcesses, afterTransactionProcesses );
|
||||
}
|
||||
|
||||
|
@ -561,48 +662,66 @@ public class ActionQueue {
|
|||
public void sortCollectionActions() {
|
||||
if ( session.getFactory().getSessionFactoryOptions().isOrderUpdatesEnabled() ) {
|
||||
// sort the updates by fk
|
||||
collectionCreations.sort();
|
||||
collectionUpdates.sort();
|
||||
collectionQueuedOps.sort();
|
||||
collectionRemovals.sort();
|
||||
if( collectionCreations != null ) {
|
||||
collectionCreations.sort();
|
||||
}
|
||||
if( collectionUpdates != null ) {
|
||||
collectionUpdates.sort();
|
||||
}
|
||||
if( collectionQueuedOps != null ) {
|
||||
collectionQueuedOps.sort();
|
||||
}
|
||||
if( collectionRemovals != null ) {
|
||||
collectionRemovals.sort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sortActions() {
|
||||
if ( session.getFactory().getSessionFactoryOptions().isOrderUpdatesEnabled() ) {
|
||||
if ( session.getFactory().getSessionFactoryOptions().isOrderUpdatesEnabled() && updates != null ) {
|
||||
// sort the updates by pk
|
||||
updates.sort();
|
||||
}
|
||||
if ( session.getFactory().getSessionFactoryOptions().isOrderInsertsEnabled() ) {
|
||||
if ( session.getFactory().getSessionFactoryOptions().isOrderInsertsEnabled() && insertions != null ) {
|
||||
insertions.sort();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearFromFlushNeededCheck(int previousCollectionRemovalSize) {
|
||||
collectionCreations.clear();
|
||||
collectionUpdates.clear();
|
||||
collectionQueuedOps.clear();
|
||||
updates.clear();
|
||||
if( collectionCreations != null ) {
|
||||
collectionCreations.clear();
|
||||
}
|
||||
if( collectionUpdates != null ) {
|
||||
collectionUpdates.clear();
|
||||
}
|
||||
if( collectionQueuedOps != null ) {
|
||||
collectionQueuedOps.clear();
|
||||
}
|
||||
if( updates != null) {
|
||||
updates.clear();
|
||||
}
|
||||
// collection deletions are a special case since update() can add
|
||||
// deletions of collections not loaded by the session.
|
||||
if ( collectionRemovals.size() > previousCollectionRemovalSize ) {
|
||||
if ( collectionRemovals != null && collectionRemovals.size() > previousCollectionRemovalSize ) {
|
||||
collectionRemovals.removeLastN( collectionRemovals.size() - previousCollectionRemovalSize );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SimplifiableConditionalExpression")
|
||||
public boolean hasAfterTransactionActions() {
|
||||
return isTransactionCoordinatorShared ? false : afterTransactionProcesses.hasActions();
|
||||
return isTransactionCoordinatorShared ? false : afterTransactionProcesses != null && afterTransactionProcesses.hasActions();
|
||||
}
|
||||
|
||||
@SuppressWarnings("SimplifiableConditionalExpression")
|
||||
public boolean hasBeforeTransactionActions() {
|
||||
return isTransactionCoordinatorShared ? false : beforeTransactionProcesses.hasActions();
|
||||
return isTransactionCoordinatorShared ? false : beforeTransactionProcesses != null && beforeTransactionProcesses.hasActions();
|
||||
}
|
||||
|
||||
public boolean hasAnyQueuedActions() {
|
||||
return !updates.isEmpty() || !insertions.isEmpty() || !unresolvedInsertions.isEmpty() || !deletions.isEmpty() || !collectionUpdates.isEmpty()
|
||||
|| !collectionQueuedOps.isEmpty() || !collectionRemovals.isEmpty() || !collectionCreations.isEmpty();
|
||||
return ( updates != null && !updates.isEmpty() ) || ( insertions != null && !insertions.isEmpty() ) || hasUnresolvedEntityInsertActions()
|
||||
|| ( deletions != null && !deletions.isEmpty()) || ( collectionUpdates != null && !collectionUpdates.isEmpty() )
|
||||
|| ( collectionQueuedOps != null && !collectionQueuedOps.isEmpty() ) || ( collectionRemovals != null && !collectionRemovals.isEmpty() )
|
||||
|| ( collectionCreations != null && !collectionCreations.isEmpty() );
|
||||
}
|
||||
|
||||
public void unScheduleDeletion(EntityEntry entry, Object rescuedEntity) {
|
||||
|
@ -612,18 +731,22 @@ public class ActionQueue {
|
|||
rescuedEntity = initializer.getImplementation( session );
|
||||
}
|
||||
}
|
||||
for ( int i = 0; i < deletions.size(); i++ ) {
|
||||
EntityDeleteAction action = deletions.get( i );
|
||||
if ( action.getInstance() == rescuedEntity ) {
|
||||
deletions.remove( i );
|
||||
return;
|
||||
if( deletions != null ) {
|
||||
for ( int i = 0; i < deletions.size(); i++ ) {
|
||||
EntityDeleteAction action = deletions.get(i);
|
||||
if (action.getInstance() == rescuedEntity) {
|
||||
deletions.remove(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for ( int i = 0; i < orphanRemovals.size(); i++ ) {
|
||||
EntityDeleteAction action = orphanRemovals.get( i );
|
||||
if ( action.getInstance() == rescuedEntity ) {
|
||||
orphanRemovals.remove( i );
|
||||
return;
|
||||
if( orphanRemovals != null ) {
|
||||
for ( int i = 0; i < orphanRemovals.size(); i++ ) {
|
||||
EntityDeleteAction action = orphanRemovals.get(i);
|
||||
if (action.getInstance() == rescuedEntity) {
|
||||
orphanRemovals.remove(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new AssertionFailure( "Unable to perform un-delete for instance " + entry.getEntityName() );
|
||||
|
@ -637,11 +760,19 @@ public class ActionQueue {
|
|||
*/
|
||||
public void serialize(ObjectOutputStream oos) throws IOException {
|
||||
LOG.trace( "Serializing action-queue" );
|
||||
|
||||
if( unresolvedInsertions == null ) {
|
||||
unresolvedInsertions = new UnresolvedEntityInsertActions();
|
||||
}
|
||||
unresolvedInsertions.serialize( oos );
|
||||
|
||||
for ( ExecutableList<?> l : executableLists ) {
|
||||
l.writeExternal( oos );
|
||||
for ( ListProvider p : EXECUTABLE_LISTS ) {
|
||||
ExecutableList<?> l = p.get(this);
|
||||
if( l == null ) {
|
||||
oos.writeBoolean(false);
|
||||
} else {
|
||||
oos.writeBoolean(true);
|
||||
l.writeExternal(oos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -657,18 +788,27 @@ public class ActionQueue {
|
|||
public static ActionQueue deserialize(ObjectInputStream ois, SessionImplementor session) throws IOException, ClassNotFoundException {
|
||||
final boolean traceEnabled = LOG.isTraceEnabled();
|
||||
if ( traceEnabled ) {
|
||||
LOG.trace( "Deserializing action-queue" );
|
||||
LOG.trace("Deserializing action-queue");
|
||||
}
|
||||
ActionQueue rtn = new ActionQueue( session );
|
||||
|
||||
rtn.unresolvedInsertions = UnresolvedEntityInsertActions.deserialize( ois, session );
|
||||
|
||||
for ( ExecutableList<?> l : rtn.executableLists ) {
|
||||
l.readExternal( ois );
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev( "Deserialized [{0}] entries", l.size() );
|
||||
for ( int i = 0; i < EXECUTABLE_LISTS.length; ++i ) {
|
||||
ListProvider provider = EXECUTABLE_LISTS[i];
|
||||
ExecutableList<?> l = provider.get(rtn);
|
||||
boolean notNull = ois.readBoolean();
|
||||
if( notNull ) {
|
||||
if(l == null) {
|
||||
l = provider.init(rtn);
|
||||
}
|
||||
l.readExternal( ois );
|
||||
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev( "Deserialized [{0}] entries", l.size() );
|
||||
}
|
||||
l.afterDeserialize( session );
|
||||
}
|
||||
l.afterDeserialize( session );
|
||||
}
|
||||
|
||||
return rtn;
|
||||
|
@ -898,4 +1038,9 @@ public class ActionQueue {
|
|||
|
||||
}
|
||||
|
||||
|
||||
private static abstract class ListProvider {
|
||||
abstract ExecutableList<?> get(ActionQueue instance);
|
||||
abstract ExecutableList<?> init(ActionQueue instance);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
public ExecutableList(int initialCapacity, ExecutableList.Sorter<E> sorter) {
|
||||
this.sorter = sorter;
|
||||
this.executables = new ArrayList<E>( initialCapacity );
|
||||
this.querySpaces = new HashSet<Serializable>();
|
||||
this.querySpaces = null;
|
||||
this.sorted = true;
|
||||
}
|
||||
|
||||
|
@ -109,13 +109,18 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
*/
|
||||
public Set<Serializable> getQuerySpaces() {
|
||||
if ( querySpaces == null ) {
|
||||
querySpaces = new HashSet<Serializable>();
|
||||
for ( E e : executables ) {
|
||||
Serializable[] propertySpaces = e.getPropertySpaces();
|
||||
if ( querySpaces != null && propertySpaces != null ) {
|
||||
if ( propertySpaces != null && propertySpaces.length > 0 ) {
|
||||
if( querySpaces == null ) {
|
||||
querySpaces = new HashSet<Serializable>();
|
||||
}
|
||||
Collections.addAll( querySpaces, propertySpaces );
|
||||
}
|
||||
}
|
||||
if( querySpaces == null ) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
return querySpaces;
|
||||
}
|
||||
|
@ -328,4 +333,8 @@ public class ExecutableList<E extends Executable & Comparable & Serializable> im
|
|||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "ExecutableList{size=" + executables.size() + "}";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -434,7 +434,7 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
|||
return entity;
|
||||
}
|
||||
|
||||
entity = loadFromSecondLevelCache( event, persister, options );
|
||||
entity = loadFromSecondLevelCache( event, persister, options, keyToLoad );
|
||||
if ( entity != null ) {
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev(
|
||||
|
@ -561,7 +561,8 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
|||
protected Object loadFromSecondLevelCache(
|
||||
final LoadEvent event,
|
||||
final EntityPersister persister,
|
||||
final LoadEventListener.LoadType options) {
|
||||
final LoadEventListener.LoadType options,
|
||||
EntityKey entityKey) {
|
||||
|
||||
final SessionImplementor source = event.getSession();
|
||||
final boolean useCache = persister.hasCache()
|
||||
|
@ -602,7 +603,7 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
|||
}
|
||||
|
||||
CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory );
|
||||
Object entity = convertCacheEntryToEntity( entry, event.getEntityId(), persister, event );
|
||||
Object entity = convertCacheEntryToEntity( entry, event.getEntityId(), persister, event, entityKey );
|
||||
|
||||
if ( !persister.isInstance( entity ) ) {
|
||||
throw new WrongClassException(
|
||||
|
@ -619,7 +620,8 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
|||
CacheEntry entry,
|
||||
Serializable entityId,
|
||||
EntityPersister persister,
|
||||
LoadEvent event) {
|
||||
LoadEvent event,
|
||||
EntityKey entityKey) {
|
||||
|
||||
final EventSource session = event.getSession();
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
|
@ -668,7 +670,6 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
|||
}
|
||||
|
||||
// make it circular-reference safe
|
||||
final EntityKey entityKey = session.generateEntityKey( entityId, subclassPersister );
|
||||
TwoPhaseLoad.addUninitializedCachedEntity(
|
||||
entityKey,
|
||||
entity,
|
||||
|
|
|
@ -138,7 +138,7 @@ public abstract class AbstractSessionImpl
|
|||
this,
|
||||
getHQLQueryPlan( queryString, false ).getParameterMetadata()
|
||||
);
|
||||
query.setComment( "named HQL query " + namedQueryDefinition.getName() );
|
||||
query.setComment( namedQueryDefinition.getComment() != null ? namedQueryDefinition.getComment() : namedQueryDefinition.getName() );
|
||||
if ( namedQueryDefinition.getLockOptions() != null ) {
|
||||
query.setLockOptions( namedQueryDefinition.getLockOptions() );
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ public abstract class AbstractSessionImpl
|
|||
this,
|
||||
parameterMetadata
|
||||
);
|
||||
query.setComment( "named native SQL query " + namedQueryDefinition.getName() );
|
||||
query.setComment( namedQueryDefinition.getComment() != null ? namedQueryDefinition.getComment() : namedQueryDefinition.getName() );
|
||||
return query;
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ public abstract class AbstractSessionImpl
|
|||
this,
|
||||
factory.getQueryPlanCache().getSQLParameterMetadata( nsqlqd.getQueryString() )
|
||||
);
|
||||
query.setComment( "named native SQL query " + queryName );
|
||||
query.setComment( nsqlqd.getComment() != null ? nsqlqd.getComment() : nsqlqd.getName() );
|
||||
initQuery( query, nsqlqd );
|
||||
return query;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue