1 /*
2 * Hibernate, Relational Persistence for Idiomatic Java
3 *
4 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
5 * indicated by the @author tags or express copyright attribution
6 * statements applied by the authors. All third-party contributions are
7 * distributed under license by Red Hat Middleware LLC.
8 *
9 * This copyrighted material is made available to anyone wishing to use, modify,
10 * copy, or redistribute it subject to the terms and conditions of the GNU
11 * Lesser General Public License, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this distribution; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301 USA
23 *
24 */
25 package org.hibernate.action;
26
27 import java.io.Serializable;
28
29 import org.hibernate.AssertionFailure;
30 import org.hibernate.HibernateException;
31 import org.hibernate.cache.CacheKey;
32 import org.hibernate.cache.access.SoftLock;
33 import org.hibernate.engine.EntityEntry;
34 import org.hibernate.engine.EntityKey;
35 import org.hibernate.engine.PersistenceContext;
36 import org.hibernate.engine.SessionImplementor;
37 import org.hibernate.event.PostDeleteEvent;
38 import org.hibernate.event.PostDeleteEventListener;
39 import org.hibernate.event.PreDeleteEvent;
40 import org.hibernate.event.PreDeleteEventListener;
41 import org.hibernate.event.EventSource;
42 import org.hibernate.persister.entity.EntityPersister;
43
44 public final class EntityDeleteAction extends EntityAction {
45
46 private final Object version;
47 private SoftLock lock;
48 private final boolean isCascadeDeleteEnabled;
49 private final Object[] state;
50
51 public EntityDeleteAction(
52 final Serializable id,
53 final Object[] state,
54 final Object version,
55 final Object instance,
56 final EntityPersister persister,
57 final boolean isCascadeDeleteEnabled,
58 final SessionImplementor session) {
59 super( session, id, instance, persister );
60 this.version = version;
61 this.isCascadeDeleteEnabled = isCascadeDeleteEnabled;
62 this.state = state;
63 }
64
65 public void execute() throws HibernateException {
66 Serializable id = getId();
67 EntityPersister persister = getPersister();
68 SessionImplementor session = getSession();
69 Object instance = getInstance();
70
71 boolean veto = preDelete();
72
73 Object version = this.version;
74 if ( persister.isVersionPropertyGenerated() ) {
75 // we need to grab the version value from the entity, otherwise
76 // we have issues with generated-version entities that may have
77 // multiple actions queued during the same flush
78 version = persister.getVersion( instance, session.getEntityMode() );
79 }
80
81 final CacheKey ck;
82 if ( persister.hasCache() ) {
83 ck = new CacheKey(
84 id,
85 persister.getIdentifierType(),
86 persister.getRootEntityName(),
87 session.getEntityMode(),
88 session.getFactory()
89 );
90 lock = persister.getCacheAccessStrategy().lockItem( ck, version );
91 }
92 else {
93 ck = null;
94 }
95
96 if ( !isCascadeDeleteEnabled && !veto ) {
97 persister.delete( id, version, instance, session );
98 }
99
100 //postDelete:
101 // After actually deleting a row, record the fact that the instance no longer
102 // exists on the database (needed for identity-column key generation), and
103 // remove it from the session cache
104 final PersistenceContext persistenceContext = session.getPersistenceContext();
105 EntityEntry entry = persistenceContext.removeEntry( instance );
106 if ( entry == null ) {
107 throw new AssertionFailure( "possible nonthreadsafe access to session" );
108 }
109 entry.postDelete();
110
111 EntityKey key = new EntityKey( entry.getId(), entry.getPersister(), session.getEntityMode() );
112 persistenceContext.removeEntity(key);
113 persistenceContext.removeProxy(key);
114
115 if ( persister.hasCache() ) persister.getCacheAccessStrategy().remove( ck );
116
117 postDelete();
118
119 if ( getSession().getFactory().getStatistics().isStatisticsEnabled() && !veto ) {
120 getSession().getFactory().getStatisticsImplementor()
121 .deleteEntity( getPersister().getEntityName() );
122 }
123 }
124
125 private boolean preDelete() {
126 PreDeleteEventListener[] preListeners = getSession().getListeners()
127 .getPreDeleteEventListeners();
128 boolean veto = false;
129 if (preListeners.length>0) {
130 PreDeleteEvent preEvent = new PreDeleteEvent( getInstance(), getId(), state, getPersister() ,(EventSource) getSession() );
131 for ( int i = 0; i < preListeners.length; i++ ) {
132 veto = preListeners[i].onPreDelete(preEvent) || veto;
133 }
134 }
135 return veto;
136 }
137
138 private void postDelete() {
139 PostDeleteEventListener[] postListeners = getSession().getListeners()
140 .getPostDeleteEventListeners();
141 if (postListeners.length>0) {
142 PostDeleteEvent postEvent = new PostDeleteEvent(
143 getInstance(),
144 getId(),
145 state,
146 getPersister(),
147 (EventSource) getSession()
148 );
149 for ( int i = 0; i < postListeners.length; i++ ) {
150 postListeners[i].onPostDelete(postEvent);
151 }
152 }
153 }
154
155 private void postCommitDelete() {
156 PostDeleteEventListener[] postListeners = getSession().getListeners()
157 .getPostCommitDeleteEventListeners();
158 if (postListeners.length>0) {
159 PostDeleteEvent postEvent = new PostDeleteEvent(
160 getInstance(),
161 getId(),
162 state,
163 getPersister(),
164 (EventSource) getSession()
165 );
166 for ( int i = 0; i < postListeners.length; i++ ) {
167 postListeners[i].onPostDelete(postEvent);
168 }
169 }
170 }
171
172 public void afterTransactionCompletion(boolean success) throws HibernateException {
173 if ( getPersister().hasCache() ) {
174 final CacheKey ck = new CacheKey(
175 getId(),
176 getPersister().getIdentifierType(),
177 getPersister().getRootEntityName(),
178 getSession().getEntityMode(),
179 getSession().getFactory()
180 );
181 getPersister().getCacheAccessStrategy().unlockItem( ck, lock );
182 }
183 postCommitDelete();
184 }
185
186 protected boolean hasPostCommitEventListeners() {
187 return getSession().getListeners().getPostCommitDeleteEventListeners().length>0;
188 }
189
190 }
191
192
193
194
195
196
197