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.AssertionFailure; 9 import org.hibernate.EntityMode; 10 import org.hibernate.HibernateException; 11 import org.hibernate.LockMode; 12 import org.hibernate.PersistentObjectException; 13 import org.hibernate.TransientObjectException; 14 import org.hibernate.classic.Lifecycle; 15 import org.hibernate.engine.Cascade; 16 import org.hibernate.engine.CascadingAction; 17 import org.hibernate.engine.EntityEntry; 18 import org.hibernate.engine.EntityKey; 19 import org.hibernate.engine.SessionFactoryImplementor; 20 import org.hibernate.engine.SessionImplementor; 21 import org.hibernate.engine.Status; 22 import org.hibernate.event.EventSource; 23 import org.hibernate.event.SaveOrUpdateEvent; 24 import org.hibernate.event.SaveOrUpdateEventListener; 25 import org.hibernate.persister.entity.EntityPersister; 26 import org.hibernate.pretty.MessageHelper; 27 import org.hibernate.proxy.HibernateProxy; 28 29 35 public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener implements SaveOrUpdateEventListener { 36 37 private static final Log log = LogFactory.getLog(DefaultSaveOrUpdateEventListener.class); 38 39 45 public Serializable onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException { 46 47 final SessionImplementor source = event.getSession(); 48 final Object object = event.getObject(); 49 50 final Serializable requestedId = event.getRequestedId(); 51 if ( requestedId!=null ) { 52 if ( object instanceof HibernateProxy ) { 55 ( (HibernateProxy) object ).getHibernateLazyInitializer().setIdentifier(requestedId); 56 } 57 } 58 59 if ( reassociateIfUninitializedProxy(object, source) ) { 60 log.trace("reassociated uninitialized proxy"); 61 return null; 64 } 65 66 final Object entity = source.getPersistenceContext().unproxyAndReassociate(object); 68 event.setEntity(entity); 69 event.setEntry( source.getPersistenceContext().getEntry(entity) ); 70 71 return performSaveOrUpdate(event); 72 73 } 74 75 protected boolean reassociateIfUninitializedProxy(Object object, SessionImplementor source) { 76 return source.getPersistenceContext().reassociateIfUninitializedProxy(object); 77 } 78 79 protected Serializable performSaveOrUpdate(SaveOrUpdateEvent event) { 80 81 84 int entityState = getEntityState( 85 event.getEntity(), 86 event.getEntityName(), 87 event.getEntry(), 88 event.getSession() 89 ); 90 91 switch (entityState) { 92 case DETACHED: 93 entityIsDetached(event); 94 return null; 95 case PERSISTENT: 96 return entityIsPersistent(event); 97 default: return entityIsTransient(event); 99 } 100 101 } 102 103 protected Serializable entityIsPersistent(SaveOrUpdateEvent event) throws HibernateException { 104 105 log.trace("ignoring persistent instance"); 106 107 EntityEntry entityEntry = event.getEntry(); 108 if ( entityEntry==null ) { 109 throw new AssertionFailure("entity was transient or detached"); 110 } 111 else { 112 113 if ( entityEntry.getStatus() == Status.DELETED ) { 114 throw new AssertionFailure("entity was deleted"); 115 } 116 117 final SessionFactoryImplementor factory = event.getSession().getFactory(); 118 119 Serializable requestedId = event.getRequestedId(); 120 121 Serializable savedId; 122 if ( requestedId == null ) { 123 savedId = entityEntry.getId(); 124 } 125 else { 126 127 final boolean isEqual = !entityEntry.getPersister().getIdentifierType() 128 .isEqual( requestedId, entityEntry.getId(), event.getSession().getEntityMode(), factory ); 129 130 if ( isEqual ) { 131 throw new PersistentObjectException( 132 "object passed to save() was already persistent: " + 133 MessageHelper.infoString( entityEntry.getPersister(), requestedId, factory ) 134 ); 135 } 136 137 savedId = requestedId; 138 139 } 140 141 if ( log.isTraceEnabled() ) { 142 log.trace( 143 "object already associated with session: " + 144 MessageHelper.infoString( entityEntry.getPersister(), savedId, factory ) 145 ); 146 } 147 148 return savedId; 149 150 } 151 } 152 153 159 protected Serializable entityIsTransient(SaveOrUpdateEvent event) throws HibernateException { 160 161 log.trace("saving transient instance"); 162 163 final EventSource source = event.getSession(); 164 165 EntityEntry entityEntry = event.getEntry(); 166 if ( entityEntry != null ) { 167 if ( entityEntry.getStatus() == Status.DELETED ) { 168 source.forceFlush(entityEntry); 169 } 170 else { 171 throw new AssertionFailure("entity was persistent"); 172 } 173 } 174 175 Serializable id = saveWithGeneratedOrRequestedId(event); 176 177 source.getPersistenceContext().reassociateProxy( event.getObject(), id ); 178 179 return id; 180 } 181 182 185 protected Serializable saveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) { 186 return saveWithGeneratedId( 187 event.getEntity(), 188 event.getEntityName(), 189 null, 190 event.getSession() 191 ); 192 } 193 194 200 protected void entityIsDetached(SaveOrUpdateEvent event) throws HibernateException { 201 202 log.trace("updating detached instance"); 203 204 205 if ( event.getSession().getPersistenceContext().isEntryFor( event.getEntity() ) ) { 206 throw new AssertionFailure("entity was persistent"); 208 } 209 210 Object entity = event.getEntity(); 211 212 EntityPersister persister = event.getSession().getEntityPersister( event.getEntityName(), entity ); 213 214 event.setRequestedId( getUpdateId( entity, persister, event.getRequestedId(), event.getSession().getEntityMode() ) ); 215 216 performUpdate(event, entity, persister); 217 218 } 219 220 protected Serializable getUpdateId(Object entity, EntityPersister persister, Serializable requestedId, EntityMode entityMode) 221 throws HibernateException { 222 Serializable id = persister.getIdentifier(entity, entityMode); 224 if ( id==null ) { 225 throw new TransientObjectException( 228 "The given object has a null identifier: " + 229 persister.getEntityName() 230 ); 231 } 232 else { 233 return id; 234 } 235 236 } 237 238 protected void performUpdate(SaveOrUpdateEvent event, Object entity, EntityPersister persister) 239 throws HibernateException { 240 241 if ( !persister.isMutable() ) { 242 log.trace( "immutable instance passed to doUpdate(), locking" ); 243 reassociate( event, entity, event.getRequestedId(), persister ); 244 } 245 else { 246 247 if ( log.isTraceEnabled() ) { 248 log.trace( 249 "updating " + 250 MessageHelper.infoString( persister, event.getRequestedId(), event.getSession().getFactory() ) 251 ); 252 } 253 254 final EventSource source = event.getSession(); 255 256 EntityKey key = new EntityKey( event.getRequestedId(), persister, source.getEntityMode() ); 257 258 source.getPersistenceContext().checkUniqueness( key, entity ); 259 260 if ( invokeUpdateLifecycle( entity, persister, source ) ) { 261 reassociate( event, event.getObject(), event.getRequestedId(), persister ); 262 return; 263 } 264 265 267 new OnUpdateVisitor( source, event.getRequestedId() ).process( entity, persister ); 268 269 280 281 source.getPersistenceContext().addEntity( 282 entity, 283 Status.MANAGED, 284 null, key, 286 persister.getVersion( entity, source.getEntityMode() ), 287 LockMode.NONE, 288 true, 289 persister, 290 false, 291 true ); 293 294 persister.afterReassociate(entity, source); 295 296 if ( log.isTraceEnabled() ) { 297 log.trace( 298 "updating " + 299 MessageHelper.infoString( persister, event.getRequestedId(), source.getFactory() ) 300 ); 301 } 302 303 cascadeOnUpdate(event, persister, entity); 304 305 } 306 } 307 308 protected boolean invokeUpdateLifecycle(Object entity, EntityPersister persister, EventSource source) { 309 if ( persister.implementsLifecycle( source.getEntityMode() ) ) { 310 log.debug( "calling onUpdate()" ); 311 if ( ( ( Lifecycle ) entity ).onUpdate(source) ) { 312 log.debug( "update vetoed by onUpdate()" ); 313 return true; 314 } 315 } 316 return false; 317 } 318 319 327 private void cascadeOnUpdate(SaveOrUpdateEvent event, EntityPersister persister, Object entity) { 328 EventSource source = event.getSession(); 329 source.getPersistenceContext().incrementCascadeLevel(); 330 try { 331 new Cascade(CascadingAction.SAVE_UPDATE, Cascade.AFTER_UPDATE, source) 332 .cascade(persister, entity); 333 } 334 finally { 335 source.getPersistenceContext().decrementCascadeLevel(); 336 } 337 } 338 339 protected CascadingAction getCascadeAction() { 340 return CascadingAction.SAVE_UPDATE; 341 } 342 } 343 | Popular Tags |