1 package org.hibernate.engine; 3 4 import org.apache.commons.logging.Log; 5 import org.apache.commons.logging.LogFactory; 6 import org.hibernate.AssertionFailure; 7 import org.hibernate.EntityMode; 8 import org.hibernate.HibernateException; 9 import org.hibernate.collection.PersistentCollection; 10 import org.hibernate.persister.collection.CollectionPersister; 11 import org.hibernate.pretty.MessageHelper; 12 import org.hibernate.type.CollectionType; 13 import org.hibernate.type.Type; 14 15 19 public final class Collections { 20 21 private Collections() {} 22 23 private static final Log log = LogFactory.getLog(Collections.class); 24 25 31 public static void processUnreachableCollection(PersistentCollection coll, SessionImplementor session) 32 throws HibernateException { 33 34 if ( coll.getOwner()==null ) { 35 processNeverReferencedCollection(coll, session); 36 } 37 else { 38 processDereferencedCollection(coll, session); 39 } 40 41 } 42 43 private static void processDereferencedCollection(PersistentCollection coll, SessionImplementor session) 44 throws HibernateException { 45 46 final PersistenceContext persistenceContext = session.getPersistenceContext(); 47 CollectionEntry entry = persistenceContext.getCollectionEntry(coll); 48 49 if ( log.isDebugEnabled() && entry.getLoadedPersister() != null ) 50 log.debug( 51 "Collection dereferenced: " + 52 MessageHelper.collectionInfoString( 53 entry.getLoadedPersister(), 54 entry.getLoadedKey(), 55 session.getFactory() 56 ) 57 ); 58 59 boolean hasOrphanDelete = entry.getLoadedPersister() != null && 61 entry.getLoadedPersister().hasOrphanDelete(); 62 if (hasOrphanDelete) { 63 EntityKey key = new EntityKey( 64 entry.getLoadedPersister().getOwnerEntityPersister() 65 .getIdentifier( coll.getOwner(), session.getEntityMode() ), 66 entry.getLoadedPersister().getOwnerEntityPersister(), 67 session.getEntityMode() 68 ); 69 Object owner = persistenceContext.getEntity(key); 70 if ( owner == null ) throw new AssertionFailure( "owner not associated with session" ); 71 EntityEntry e = persistenceContext.getEntry(owner); 72 if ( e != null && e.getStatus() != Status.DELETED && e.getStatus() != Status.GONE ) { 74 throw new HibernateException( 75 "Don't dereference a collection with cascade=\"all-delete-orphan\": " + 76 coll.getRole() 77 ); 78 } 79 } 80 81 entry.setCurrentPersister(null); 83 entry.setCurrentKey(null); 84 prepareCollectionForUpdate( coll, entry, session.getEntityMode(), session.getFactory() ); 85 86 } 87 88 private static void processNeverReferencedCollection(PersistentCollection coll, SessionImplementor session) 89 throws HibernateException { 90 91 final PersistenceContext persistenceContext = session.getPersistenceContext(); 92 CollectionEntry entry = persistenceContext.getCollectionEntry(coll); 93 94 log.debug( 95 "Found collection with unloaded owner: " + 96 MessageHelper.collectionInfoString( 97 entry.getLoadedPersister(), 98 entry.getLoadedKey(), 99 session.getFactory() 100 ) 101 ); 102 103 entry.setCurrentPersister( entry.getLoadedPersister() ); 104 entry.setCurrentKey( entry.getLoadedKey() ); 105 106 prepareCollectionForUpdate( coll, entry, session.getEntityMode(), session.getFactory() ); 107 108 } 109 110 118 public static void processReachableCollection( 119 PersistentCollection collection, 120 Type type, 121 Object entity, 122 SessionImplementor session) 123 throws HibernateException { 124 125 collection.setOwner(entity); 126 127 CollectionEntry ce = session.getPersistenceContext().getCollectionEntry(collection); 128 129 if ( ce == null ) { 130 throw new HibernateException( "Found two representations of same collection" ); 132 } 133 134 if ( ce.isReached() ) { 137 throw new HibernateException( "Found shared references to a collection" ); 139 } 140 ce.setReached(true); 141 142 CollectionType pctype = (CollectionType) type; 143 CollectionPersister persister = session.getFactory().getCollectionPersister( pctype.getRole() ); 144 ce.setCurrentPersister(persister); 145 ce.setCurrentKey( pctype.getKeyOfOwner(entity, session) ); 147 if ( log.isDebugEnabled() ) { 148 log.debug( 149 "Collection found: " + 150 MessageHelper.collectionInfoString( persister, ce.getCurrentKey(), session.getFactory() ) + 151 ", was: " + 152 MessageHelper.collectionInfoString( ce.getLoadedPersister(), ce.getLoadedKey(), session.getFactory() ) + 153 ( collection.wasInitialized() ? " (initialized)" : " (uninitialized)" ) 154 ); 155 } 156 157 prepareCollectionForUpdate( collection, ce, session.getEntityMode(), session.getFactory() ); 158 159 } 160 161 166 private static void prepareCollectionForUpdate( 167 PersistentCollection collection, 168 CollectionEntry entry, 169 EntityMode entityMode, 170 SessionFactoryImplementor factory) 171 throws HibernateException { 172 173 if ( entry.isProcessed() ) { 174 throw new AssertionFailure( "collection was processed twice by flush()" ); 175 } 176 entry.setProcessed(true); 177 178 if ( entry.getLoadedPersister() != null || entry.getCurrentPersister() != null ) { 180 boolean ownerChanged = entry.getLoadedPersister() != entry.getCurrentPersister() || !entry.getCurrentPersister() 182 .getKeyType().isEqual( entry.getLoadedKey(), 184 entry.getCurrentKey(), 185 entityMode, factory 186 ); 187 188 if (ownerChanged) { 189 190 if ( 192 entry.getLoadedPersister() != null && 193 entry.getCurrentPersister() != null && 194 entry.getLoadedPersister().hasOrphanDelete() 195 ) { 196 throw new HibernateException( 197 "Don't change the reference to a collection with cascade=\"all-delete-orphan\": " + 198 collection.getRole() 199 ); 200 } 201 202 if ( entry.getCurrentPersister() != null ) entry.setDorecreate(true); 205 if ( entry.getLoadedPersister() != null ) { 206 entry.setDoremove(true); if ( entry.isDorecreate() ) { 208 log.trace( "Forcing collection initialization" ); 209 collection.forceInitialization(); } 211 } 212 213 } 214 else if ( collection.isDirty() ) { entry.setDoupdate(true); 216 } 217 218 } 219 220 } 221 222 } 223 | Popular Tags |