📄 actionqueue.java
字号:
public int numberOfCollectionUpdates() { return collectionUpdates.size(); } public int numberOfCollectionCreations() { return collectionCreations.size(); } public int numberOfDeletions() { return deletions.size(); } public int numberOfUpdates() { return updates.size(); } public int numberOfInsertions() { return insertions.size(); } public void sortCollectionActions() { if ( session.getFactory().getSettings().isOrderUpdatesEnabled() ) { //sort the updates by fk java.util.Collections.sort( collectionCreations ); java.util.Collections.sort( collectionUpdates ); java.util.Collections.sort( collectionRemovals ); } } public void sortActions() { if ( session.getFactory().getSettings().isOrderUpdatesEnabled() ) { //sort the updates by pk java.util.Collections.sort( updates ); } if ( session.getFactory().getSettings().isOrderInsertsEnabled() ) { sortInsertActions(); } } /** * Order the {@link #insertions} queue such that we group inserts * against the same entity together (without violating constraints). The * original order is generated by cascade order, which in turn is based on * the directionality of foreign-keys. So even though we will be changing * the ordering here, we need to make absolutely certain that we do not * circumvent this FK ordering to the extent of causing constraint * violations */ private void sortInsertActions() { new InsertActionSorter().sort(); } public ArrayList cloneDeletions() { return ( ArrayList ) deletions.clone(); } public void clearFromFlushNeededCheck(int previousCollectionRemovalSize) { collectionCreations.clear(); collectionUpdates.clear(); updates.clear(); // collection deletions are a special case since update() can add // deletions of collections not loaded by the session. for ( int i = collectionRemovals.size() - 1; i >= previousCollectionRemovalSize; i-- ) { collectionRemovals.remove( i ); } } public boolean hasAfterTransactionActions() { return executions.size() > 0; } public boolean hasAnyQueuedActions() { return updates.size() > 0 || insertions.size() > 0 || deletions.size() > 0 || collectionUpdates.size() > 0 || collectionRemovals.size() > 0 || collectionCreations.size() > 0; } /** * Used by the owning session to explicitly control serialization of the * action queue * * @param oos The stream to which the action queue should get written * * @throws IOException */ public void serialize(ObjectOutputStream oos) throws IOException { log.trace( "serializing action-queue" ); int queueSize = insertions.size(); log.trace( "starting serialization of [" + queueSize + "] insertions entries" ); oos.writeInt( queueSize ); for ( int i = 0; i < queueSize; i++ ) { oos.writeObject( insertions.get( i ) ); } queueSize = deletions.size(); log.trace( "starting serialization of [" + queueSize + "] deletions entries" ); oos.writeInt( queueSize ); for ( int i = 0; i < queueSize; i++ ) { oos.writeObject( deletions.get( i ) ); } queueSize = updates.size(); log.trace( "starting serialization of [" + queueSize + "] updates entries" ); oos.writeInt( queueSize ); for ( int i = 0; i < queueSize; i++ ) { oos.writeObject( updates.get( i ) ); } queueSize = collectionUpdates.size(); log.trace( "starting serialization of [" + queueSize + "] collectionUpdates entries" ); oos.writeInt( queueSize ); for ( int i = 0; i < queueSize; i++ ) { oos.writeObject( collectionUpdates.get( i ) ); } queueSize = collectionRemovals.size(); log.trace( "starting serialization of [" + queueSize + "] collectionRemovals entries" ); oos.writeInt( queueSize ); for ( int i = 0; i < queueSize; i++ ) { oos.writeObject( collectionRemovals.get( i ) ); } queueSize = collectionCreations.size(); log.trace( "starting serialization of [" + queueSize + "] collectionCreations entries" ); oos.writeInt( queueSize ); for ( int i = 0; i < queueSize; i++ ) { oos.writeObject( collectionCreations.get( i ) ); } } /** * Used by the owning session to explicitly control deserialization of the * action queue * * @param ois The stream from which to read the action queue * * @throws IOException */ public static ActionQueue deserialize( ObjectInputStream ois, SessionImplementor session) throws IOException, ClassNotFoundException { log.trace( "deserializing action-queue" ); ActionQueue rtn = new ActionQueue( session ); int queueSize = ois.readInt(); log.trace( "starting deserialization of [" + queueSize + "] insertions entries" ); rtn.insertions = new ArrayList( queueSize ); for ( int i = 0; i < queueSize; i++ ) { rtn.insertions.add( ois.readObject() ); } queueSize = ois.readInt(); log.trace( "starting deserialization of [" + queueSize + "] deletions entries" ); rtn.deletions = new ArrayList( queueSize ); for ( int i = 0; i < queueSize; i++ ) { rtn.deletions.add( ois.readObject() ); } queueSize = ois.readInt(); log.trace( "starting deserialization of [" + queueSize + "] updates entries" ); rtn.updates = new ArrayList( queueSize ); for ( int i = 0; i < queueSize; i++ ) { rtn.updates.add( ois.readObject() ); } queueSize = ois.readInt(); log.trace( "starting deserialization of [" + queueSize + "] collectionUpdates entries" ); rtn.collectionUpdates = new ArrayList( queueSize ); for ( int i = 0; i < queueSize; i++ ) { rtn.collectionUpdates.add( ois.readObject() ); } queueSize = ois.readInt(); log.trace( "starting deserialization of [" + queueSize + "] collectionRemovals entries" ); rtn.collectionRemovals = new ArrayList( queueSize ); for ( int i = 0; i < queueSize; i++ ) { rtn.collectionRemovals.add( ois.readObject() ); } queueSize = ois.readInt(); log.trace( "starting deserialization of [" + queueSize + "] collectionCreations entries" ); rtn.collectionCreations = new ArrayList( queueSize ); for ( int i = 0; i < queueSize; i++ ) { rtn.collectionCreations.add( ois.readObject() ); } return rtn; } /** * Sorts the insert actions using more hashes. * * @author Jay Erb */ private class InsertActionSorter { // the mapping of entity names to their latest batch numbers. private HashMap latestBatches = new HashMap(); private HashMap entityBatchNumber; // the map of batch numbers to EntityInsertAction lists private HashMap actionBatches = new HashMap(); public InsertActionSorter() { //optimize the hash size to eliminate a rehash. entityBatchNumber = new HashMap( insertions.size() + 1, 1.0f ); } /** * Sort the insert actions. */ public void sort() { // the list of entity names that indicate the batch number for ( Iterator actionItr = insertions.iterator(); actionItr.hasNext(); ) { EntityInsertAction action = ( EntityInsertAction ) actionItr.next(); // remove the current element from insertions. It will be added back later. String entityName = action.getEntityName(); // the entity associated with the current action. Object currentEntity = action.getInstance(); Integer batchNumber; if ( latestBatches.containsKey( entityName ) ) { // There is already an existing batch for this type of entity. // Check to see if the latest batch is acceptable. batchNumber = findBatchNumber( action, entityName ); } else { // add an entry for this type of entity. // we can be assured that all referenced entities have already // been processed, // so specify that this entity is with the latest batch. // doing the batch number before adding the name to the list is // a faster way to get an accurate number. batchNumber = new Integer( actionBatches.size() ); latestBatches.put( entityName, batchNumber ); } entityBatchNumber.put( currentEntity, batchNumber ); addToBatch( batchNumber, action ); } insertions.clear(); // now rebuild the insertions list. There is a batch for each entry in the name list. for ( int i = 0; i < actionBatches.size(); i++ ) { List batch = ( List ) actionBatches.get( new Integer( i ) ); for ( Iterator batchItr = batch.iterator(); batchItr.hasNext(); ) { EntityInsertAction action = ( EntityInsertAction ) batchItr.next(); insertions.add( action ); } } } /** * Finds an acceptable batch for this entity to be a member. */ private Integer findBatchNumber(EntityInsertAction action, String entityName) { // loop through all the associated entities and make sure they have been // processed before the latest // batch associated with this entity type. // the current batch number is the latest batch for this entity type. Integer latestBatchNumberForType = ( Integer ) latestBatches.get( entityName ); // loop through all the associations of the current entity and make sure that they are processed // before the current batch number Object[] propertyValues = action.getState(); Type[] propertyTypes = action.getPersister().getClassMetadata() .getPropertyTypes(); for ( int i = 0; i < propertyValues.length; i++ ) { Object value = propertyValues[i]; Type type = propertyTypes[i]; if ( type.isEntityType() && value != null ) { // find the batch number associated with the current association, if any. Integer associationBatchNumber = ( Integer ) entityBatchNumber.get( value ); if ( associationBatchNumber != null && associationBatchNumber.compareTo( latestBatchNumberForType ) > 0 ) { // create a new batch for this type. The batch number is the number of current batches. latestBatchNumberForType = new Integer( actionBatches.size() ); latestBatches.put( entityName, latestBatchNumberForType ); // since this entity will now be processed in the latest possible batch, // we can be assured that it will come after all other associations, // there's not need to continue checking. break; } } } return latestBatchNumberForType; } private void addToBatch(Integer batchNumber, EntityInsertAction action) { List actions = ( List ) actionBatches.get( batchNumber ); if ( actions == null ) { actions = new LinkedList(); actionBatches.put( batchNumber, actions ); } actions.add( action ); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -