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
This commit is contained in:
Stuart Douglas 2015-04-15 14:03:39 +10:00 committed by Steve Ebersole
parent fa7851058c
commit 991ff265da
5 changed files with 281 additions and 121 deletions

View File

@ -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 ) {

View File

@ -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,47 +127,20 @@ 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 ) {
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();
}
}
/**
* Adds an entity insert action
@ -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 {
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,9 +429,11 @@ public class ActionQueue {
public void beforeTransactionCompletion() {
if ( !isTransactionCoordinatorShared ) {
// Execute completion actions only in transaction owner (aka parent session).
if( beforeTransactionProcesses != null ) {
beforeTransactionProcesses.beforeTransactionCompletion();
}
}
}
/**
* Check whether any insertion or deletion actions are currently queued.
@ -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
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) {
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,20 +731,24 @@ public class ActionQueue {
rescuedEntity = initializer.getImplementation( session );
}
}
if( deletions != null ) {
for ( int i = 0; i < deletions.size(); i++ ) {
EntityDeleteAction action = deletions.get( i );
if ( action.getInstance() == rescuedEntity ) {
deletions.remove( i );
EntityDeleteAction action = deletions.get(i);
if (action.getInstance() == rescuedEntity) {
deletions.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 );
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,19 +788,28 @@ 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 ) {
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 );
}
}
return rtn;
}
@ -898,4 +1038,9 @@ public class ActionQueue {
}
private static abstract class ListProvider {
abstract ExecutableList<?> get(ActionQueue instance);
abstract ExecutableList<?> init(ActionQueue instance);
}
}

View File

@ -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() + "}";
}
}

View File

@ -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,

View File

@ -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;
}