1 package org.hibernate.event.def; 3 4 import java.util.Iterator ; 5 import java.util.List ; 6 import java.util.Map ; 7 8 import org.apache.commons.logging.Log; 9 import org.apache.commons.logging.LogFactory; 10 import org.hibernate.HibernateException; 11 import org.hibernate.action.CollectionRecreateAction; 12 import org.hibernate.action.CollectionRemoveAction; 13 import org.hibernate.action.CollectionUpdateAction; 14 import org.hibernate.collection.PersistentCollection; 15 import org.hibernate.engine.ActionQueue; 16 import org.hibernate.engine.Cascade; 17 import org.hibernate.engine.CascadingAction; 18 import org.hibernate.engine.CollectionEntry; 19 import org.hibernate.engine.CollectionKey; 20 import org.hibernate.engine.Collections; 21 import org.hibernate.engine.EntityEntry; 22 import org.hibernate.engine.PersistenceContext; 23 import org.hibernate.engine.Status; 24 import org.hibernate.event.EventSource; 25 import org.hibernate.event.FlushEntityEvent; 26 import org.hibernate.event.FlushEvent; 27 import org.hibernate.engine.SessionImplementor; 28 import org.hibernate.persister.entity.EntityPersister; 29 import org.hibernate.pretty.Printer; 30 import org.hibernate.util.IdentityMap; 31 32 37 public abstract class AbstractFlushingEventListener extends AbstractEventListener { 38 39 private static final Log log = LogFactory.getLog(AbstractFlushingEventListener.class); 40 41 45 53 protected void flushEverythingToExecutions(FlushEvent event) throws HibernateException { 54 55 log.trace("flushing session"); 56 57 EventSource session = event.getSession(); 58 59 final PersistenceContext persistenceContext = session.getPersistenceContext(); 60 session.getInterceptor().preFlush( persistenceContext.getEntitiesByKey().values().iterator() ); 61 62 prepareEntityFlushes(session); 63 prepareCollectionFlushes(session); 67 71 persistenceContext.setFlushing(true); 72 try { 73 flushEntities(event); 74 flushCollections(session); 75 } 76 finally { 77 persistenceContext.setFlushing(false); 78 } 79 80 if ( log.isDebugEnabled() ) { 82 log.debug( "Flushed: " + 83 session.getActionQueue().numberOfInsertions() + " insertions, " + 84 session.getActionQueue().numberOfUpdates() + " updates, " + 85 session.getActionQueue().numberOfDeletions() + " deletions to " + 86 persistenceContext.getEntityEntries().size() + " objects" 87 ); 88 log.debug( "Flushed: " + 89 session.getActionQueue().numberOfCollectionCreations() + " (re)creations, " + 90 session.getActionQueue().numberOfCollectionUpdates() + " updates, " + 91 session.getActionQueue().numberOfCollectionRemovals() + " removals to " + 92 persistenceContext.getCollectionEntries().size() + " collections" 93 ); 94 new Printer( session.getFactory() ).toString( persistenceContext.getEntitiesByKey().values().iterator(), session.getEntityMode() ); 95 } 96 } 97 98 103 private void prepareEntityFlushes(EventSource session) throws HibernateException { 104 105 log.debug("processing flush-time cascades"); 106 107 final Map.Entry [] list = IdentityMap.concurrentEntries( session.getPersistenceContext().getEntityEntries() ); 108 final int size = list.length; 110 for ( int i=0; i<size; i++ ) { 111 Map.Entry me = list[i]; 112 EntityEntry entry = (EntityEntry) me.getValue(); 113 Status status = entry.getStatus(); 114 if ( status == Status.MANAGED || status == Status.SAVING ) { 115 cascadeOnFlush( session, entry.getPersister(), me.getKey() ); 116 } 117 } 118 } 119 120 private void cascadeOnFlush(EventSource session, EntityPersister persister, Object object) 121 throws HibernateException { 122 session.getPersistenceContext().incrementCascadeLevel(); 123 try { 124 new Cascade( getCascadingAction(), Cascade.BEFORE_FLUSH, session ) 125 .cascade( persister, object, getAnything() ); 126 } 127 finally { 128 session.getPersistenceContext().decrementCascadeLevel(); 129 } 130 } 131 132 protected Object getAnything() { return null; } 133 134 protected CascadingAction getCascadingAction() { 135 return CascadingAction.SAVE_UPDATE; 136 } 137 138 142 private void prepareCollectionFlushes(SessionImplementor session) throws HibernateException { 143 144 147 log.debug("dirty checking collections"); 148 149 final List list = IdentityMap.entries( session.getPersistenceContext().getCollectionEntries() ); 150 final int size = list.size(); 151 for ( int i = 0; i < size; i++ ) { 152 Map.Entry e = ( Map.Entry ) list.get( i ); 153 ( (CollectionEntry) e.getValue() ).preFlush( (PersistentCollection) e.getKey() ); 154 } 155 } 156 157 162 private void flushEntities(FlushEvent event) throws HibernateException { 163 164 log.trace("Flushing entities and processing referenced collections"); 165 166 170 173 final EventSource source = event.getSession(); 174 175 final Map.Entry [] list = IdentityMap.concurrentEntries( source.getPersistenceContext().getEntityEntries() ); 176 final int size = list.length; 177 for ( int i = 0; i < size; i++ ) { 178 179 181 Map.Entry me = list[i]; 182 EntityEntry entry = (EntityEntry) me.getValue(); 183 Status status = entry.getStatus(); 184 185 if ( status != Status.LOADING && status != Status.GONE ) { 186 FlushEntityEvent entityEvent = new FlushEntityEvent( source, me.getKey(), entry ); 187 source.getListeners().getFlushEntityEventListener().onFlushEntity(entityEvent); 188 } 189 } 190 191 source.getActionQueue().sortUpdateActions(); 192 } 193 194 198 private void flushCollections(EventSource session) throws HibernateException { 199 200 log.trace("Processing unreferenced collections"); 201 202 List list = IdentityMap.entries( session.getPersistenceContext().getCollectionEntries() ); 203 int size = list.size(); 204 for ( int i = 0; i < size; i++ ) { 205 Map.Entry me = ( Map.Entry ) list.get( i ); 206 CollectionEntry ce = (CollectionEntry) me.getValue(); 207 if ( !ce.isReached() && !ce.isIgnore() ) { 208 Collections.processUnreachableCollection( (PersistentCollection) me.getKey(), session ); 209 } 210 } 211 212 214 log.trace( "Scheduling collection removes/(re)creates/updates" ); 215 216 list = IdentityMap.entries( session.getPersistenceContext().getCollectionEntries() ); 217 size = list.size(); 218 ActionQueue actionQueue = session.getActionQueue(); 219 for ( int i = 0; i < size; i++ ) { 220 Map.Entry me = (Map.Entry ) list.get(i); 221 PersistentCollection coll = (PersistentCollection) me.getKey(); 222 CollectionEntry ce = (CollectionEntry) me.getValue(); 223 224 if ( ce.isDorecreate() ) { 225 actionQueue.addAction( 226 new CollectionRecreateAction( 227 coll, 228 ce.getCurrentPersister(), 229 ce.getCurrentKey(), 230 session 231 ) 232 ); 233 } 234 if ( ce.isDoremove() ) { 235 actionQueue.addAction( 236 new CollectionRemoveAction( 237 coll, 238 ce.getLoadedPersister(), 239 ce.getLoadedKey(), 240 ce.isSnapshotEmpty(coll), 241 session 242 ) 243 ); 244 } 245 if ( ce.isDoupdate() ) { 246 actionQueue.addAction( 247 new CollectionUpdateAction( 248 coll, 249 ce.getLoadedPersister(), 250 ce.getLoadedKey(), 251 ce.isSnapshotEmpty(coll), 252 session 253 ) 254 ); 255 } 256 257 } 258 259 actionQueue.sortCollectionActions(); 260 261 } 262 263 275 protected void performExecutions(EventSource session) throws HibernateException { 276 277 log.trace("executing flush"); 278 279 try { 280 session.getActionQueue().prepareActions(); 284 session.getActionQueue().executeActions(); 285 } 286 catch (HibernateException he) { 287 log.error("Could not synchronize database state with session", he); 288 throw he; 289 } 290 } 291 292 293 297 302 protected void postFlush(SessionImplementor session) throws HibernateException { 303 304 log.trace( "post flush" ); 305 306 final PersistenceContext persistenceContext = session.getPersistenceContext(); 307 persistenceContext.getCollectionsByKey().clear(); 308 persistenceContext.getBatchFetchQueue() 309 .clearSubselects(); 311 Iterator iter = persistenceContext.getCollectionEntries().entrySet().iterator(); 312 while ( iter.hasNext() ) { 313 Map.Entry me = (Map.Entry ) iter.next(); 314 CollectionEntry collectionEntry = (CollectionEntry) me.getValue(); 315 PersistentCollection persistentCollection = (PersistentCollection) me.getKey(); 316 collectionEntry.postFlush(persistentCollection); 317 if ( collectionEntry.getLoadedPersister() == null ) { 318 persistenceContext.getCollectionEntries() 321 .remove(persistentCollection); 322 } 323 else { 324 CollectionKey collectionKey = new CollectionKey( 326 collectionEntry.getLoadedPersister(), 327 collectionEntry.getLoadedKey(), 328 session.getEntityMode() 329 ); 330 persistenceContext.getCollectionsByKey() 331 .put(collectionKey, persistentCollection); 332 } 333 } 334 335 session.getInterceptor() 336 .postFlush( persistenceContext.getEntitiesByKey().values().iterator() ); 337 338 } 339 340 } 341 | Popular Tags |