1 package org.hibernate.event.def; 3 4 import java.io.Serializable ; 5 6 import org.apache.commons.logging.Log; 7 import org.apache.commons.logging.LogFactory; 8 import org.hibernate.CacheMode; 9 import org.hibernate.HibernateException; 10 import org.hibernate.LockMode; 11 import org.hibernate.TransientObjectException; 12 import org.hibernate.action.EntityDeleteAction; 13 import org.hibernate.classic.Lifecycle; 14 import org.hibernate.engine.Cascade; 15 import org.hibernate.engine.CascadingAction; 16 import org.hibernate.engine.EntityEntry; 17 import org.hibernate.engine.EntityKey; 18 import org.hibernate.engine.ForeignKeys; 19 import org.hibernate.engine.Nullability; 20 import org.hibernate.engine.PersistenceContext; 21 import org.hibernate.engine.Status; 22 import org.hibernate.event.DeleteEvent; 23 import org.hibernate.event.DeleteEventListener; 24 import org.hibernate.event.EventSource; 25 import org.hibernate.persister.entity.EntityPersister; 26 import org.hibernate.pretty.MessageHelper; 27 import org.hibernate.type.Type; 28 import org.hibernate.type.TypeFactory; 29 30 31 37 public class DefaultDeleteEventListener extends AbstractEventListener implements DeleteEventListener { 38 39 private static final Log log = LogFactory.getLog(DefaultDeleteEventListener.class); 40 41 46 public void onDelete(DeleteEvent event) throws HibernateException { 47 final EventSource source = event.getSession(); 48 49 final PersistenceContext persistenceContext = source.getPersistenceContext(); 50 Object entity = persistenceContext.unproxyAndReassociate( event.getObject() ); 51 EntityEntry entityEntry = persistenceContext.getEntry(entity); 52 53 final EntityPersister persister; 54 final Serializable id; 55 final Object version; 56 if ( entityEntry == null ) { 57 log.trace( "deleting a detached instance" ); 58 59 persister = source.getEntityPersister( event.getEntityName(), entity ); 60 id = persister.getIdentifier( entity, source.getEntityMode() ); 61 62 if ( id == null ) { 63 throw new TransientObjectException( 64 "the detached instance passed to delete() had a null identifier" 65 ); 66 } 67 68 EntityKey key = new EntityKey( id, persister, source.getEntityMode() ); 69 70 persistenceContext.checkUniqueness(key, entity); 71 72 new OnUpdateVisitor( source, id ).process( entity, persister ); 73 74 version = persister.getVersion( entity, source.getEntityMode() ); 75 76 entityEntry = persistenceContext.addEntity( 77 entity, 78 Status.MANAGED, 79 persister.getPropertyValues( entity, source.getEntityMode() ), 80 key, 81 version, 82 LockMode.NONE, 83 true, 84 persister, 85 false, 86 false 87 ); 88 } 89 else { 90 log.trace( "deleting a persistent instance" ); 91 92 if ( entityEntry.getStatus() == Status.DELETED || entityEntry.getStatus() == Status.GONE ) { 93 log.trace( "object was already deleted" ); 94 return; 95 } 96 persister = entityEntry.getPersister(); 97 id = entityEntry.getId(); 98 version = entityEntry.getVersion(); 99 } 100 101 107 108 if ( invokeDeleteLifecycle( source, entity, persister ) ) return; 109 110 deleteEntity( source, entity, entityEntry, event.isCascadeDeleteEnabled(), persister ); 111 112 if ( source.getFactory().getSettings().isIdentifierRollbackEnabled() ) { 113 persister.resetIdentifier( entity, id, version, source.getEntityMode() ); 114 } 115 116 } 117 118 protected final void deleteEntity( 119 final EventSource session, 120 final Object entity, 121 final EntityEntry entityEntry, 122 final boolean isCascadeDeleteEnabled, 123 final EntityPersister persister) 124 throws HibernateException { 125 126 if ( log.isTraceEnabled() ) { 127 log.trace( 128 "deleting " + 129 MessageHelper.infoString( persister, entityEntry.getId(), session.getFactory() ) 130 ); 131 } 132 133 final PersistenceContext persistenceContext = session.getPersistenceContext(); 134 135 Type[] propTypes = persister.getPropertyTypes(); 136 137 final Object version = entityEntry.getVersion(); 138 139 final Object [] currentState; 140 if ( entityEntry.getLoadedState() == null ) { currentState = persister.getPropertyValues( entity, session.getEntityMode() ); 142 } 143 else { 144 currentState = entityEntry.getLoadedState(); 145 } 146 147 final Object [] deletedState = new Object [propTypes.length]; 148 TypeFactory.deepCopy( 149 currentState, 150 propTypes, 151 persister.getPropertyUpdateability(), 152 deletedState, 153 session 154 ); 155 entityEntry.setDeletedState(deletedState); 156 157 session.getInterceptor().onDelete( 158 entity, 159 entityEntry.getId(), 160 deletedState, 161 persister.getPropertyNames(), 162 propTypes 163 ); 164 165 persistenceContext.setEntryStatus(entityEntry, Status.DELETED); 167 EntityKey key = new EntityKey( entityEntry.getId(), persister, session.getEntityMode() ); 168 169 cascadeBeforeDelete(session, persister, entity, entityEntry); 170 171 new ForeignKeys.Nullifier(entity, true, false, session) 172 .nullifyTransientReferences( entityEntry.getDeletedState(), propTypes ); 173 new Nullability(session).checkNullability( entityEntry.getDeletedState(), persister, true ); 174 persistenceContext.getNullifiableEntityKeys().add(key); 175 176 session.getActionQueue().addAction( 178 new EntityDeleteAction( 179 entityEntry.getId(), 180 deletedState, 181 version, 182 entity, 183 persister, 184 isCascadeDeleteEnabled, 185 session 186 ) 187 ); 188 189 cascadeAfterDelete(session, persister, entity); 190 191 196 } 197 198 protected boolean invokeDeleteLifecycle(EventSource session, Object entity, EntityPersister persister) { 199 if ( persister.implementsLifecycle( session.getEntityMode() ) ) { 200 log.debug( "calling onDelete()" ); 201 if ( ( (Lifecycle) entity ).onDelete(session) ) { 202 log.debug("deletion vetoed by onDelete()"); 203 return true; 204 } 205 } 206 return false; 207 } 208 209 protected void cascadeBeforeDelete( 210 EventSource session, 211 EntityPersister persister, 212 Object entity, 213 EntityEntry entityEntry) throws HibernateException { 214 215 CacheMode cacheMode = session.getCacheMode(); 216 session.setCacheMode(CacheMode.GET); 217 session.getPersistenceContext().incrementCascadeLevel(); 218 try { 219 new Cascade(CascadingAction.DELETE, Cascade.AFTER_INSERT_BEFORE_DELETE, session) 221 .cascade(persister, entity); 222 } 223 finally { 224 session.getPersistenceContext().decrementCascadeLevel(); 225 session.setCacheMode(cacheMode); 226 } 227 } 228 229 protected void cascadeAfterDelete( 230 EventSource session, 231 EntityPersister persister, 232 Object entity) throws HibernateException { 233 234 CacheMode cacheMode = session.getCacheMode(); 235 session.setCacheMode(CacheMode.GET); 236 session.getPersistenceContext().incrementCascadeLevel(); 237 try { 238 new Cascade(CascadingAction.DELETE, Cascade.BEFORE_INSERT_AFTER_DELETE, session) 240 .cascade(persister, entity); 241 } 242 finally { 243 session.getPersistenceContext().decrementCascadeLevel(); 244 session.setCacheMode(cacheMode); 245 } 246 } 247 248 } 249 | Popular Tags |