KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > event > def > DefaultDeleteEventListener


1 //$Id: DefaultDeleteEventListener.java,v 1.17 2005/07/20 23:59:40 epbernard Exp $
2
package org.hibernate.event.def;
3
4 import java.io.Serializable JavaDoc;
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 /**
32  * Defines the default delete event listener used by hibernate for deleting entities
33  * from the datastore in response to generated delete events.
34  *
35  * @author Steve Ebersole
36  */

37 public class DefaultDeleteEventListener extends AbstractEventListener implements DeleteEventListener {
38
39     private static final Log log = LogFactory.getLog(DefaultDeleteEventListener.class);
40
41     /** Handle the given delete event.
42      *
43      * @param event The delete event to be handled.
44      * @throws HibernateException
45      */

46     public void onDelete(DeleteEvent event) throws HibernateException {
47         final EventSource source = event.getSession();
48         
49         final PersistenceContext persistenceContext = source.getPersistenceContext();
50         Object JavaDoc entity = persistenceContext.unproxyAndReassociate( event.getObject() );
51         EntityEntry entityEntry = persistenceContext.getEntry(entity);
52
53         final EntityPersister persister;
54         final Serializable JavaDoc id;
55         final Object JavaDoc 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         /*if ( !persister.isMutable() ) {
102             throw new HibernateException(
103                     "attempted to delete an object of immutable class: " +
104                     MessageHelper.infoString(persister)
105                 );
106         }*/

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 JavaDoc 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 JavaDoc version = entityEntry.getVersion();
138
139         final Object JavaDoc[] currentState;
140         if ( entityEntry.getLoadedState() == null ) { //ie. the entity came in from update()
141
currentState = persister.getPropertyValues( entity, session.getEntityMode() );
142         }
143         else {
144             currentState = entityEntry.getLoadedState();
145         }
146         
147         final Object JavaDoc[] deletedState = new Object JavaDoc[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         // before any callbacks, etc, so subdeletions see that this deletion happened first
166
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         // Ensures that containing deletions happen before sub-deletions
177
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         // the entry will be removed after the flush, and will no longer
192
// override the stale snapshot
193
// This is now handled by removeEntity() in EntityDeleteAction
194
//persistenceContext.removeDatabaseSnapshot(key);
195

196     }
197
198     protected boolean invokeDeleteLifecycle(EventSource session, Object JavaDoc 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 JavaDoc entity,
213             EntityEntry entityEntry) throws HibernateException {
214
215         CacheMode cacheMode = session.getCacheMode();
216         session.setCacheMode(CacheMode.GET);
217         session.getPersistenceContext().incrementCascadeLevel();
218         try {
219             // cascade-delete to collections BEFORE the collection owner is deleted
220
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 JavaDoc entity) throws HibernateException {
233
234         CacheMode cacheMode = session.getCacheMode();
235         session.setCacheMode(CacheMode.GET);
236         session.getPersistenceContext().incrementCascadeLevel();
237         try {
238             // cascade-delete to many-to-one AFTER the parent was deleted
239
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