1 package org.hibernate.event.def; 3 4 import java.io.Serializable ; 5 import java.util.Map ; 6 7 import net.sf.cglib.transform.impl.InterceptFieldEnabled; 8 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 import org.hibernate.HibernateException; 12 import org.hibernate.LockMode; 13 import org.hibernate.NonUniqueObjectException; 14 import org.hibernate.action.EntityIdentityInsertAction; 15 import org.hibernate.action.EntityInsertAction; 16 import org.hibernate.classic.Lifecycle; 17 import org.hibernate.classic.Validatable; 18 import org.hibernate.engine.Cascade; 19 import org.hibernate.engine.CascadingAction; 20 import org.hibernate.engine.EntityEntry; 21 import org.hibernate.engine.EntityKey; 22 import org.hibernate.engine.ForeignKeys; 23 import org.hibernate.engine.Nullability; 24 import org.hibernate.engine.SessionImplementor; 25 import org.hibernate.engine.Status; 26 import org.hibernate.engine.Versioning; 27 import org.hibernate.event.EventSource; 28 import org.hibernate.id.IdentifierGenerationException; 29 import org.hibernate.id.IdentifierGeneratorFactory; 30 import org.hibernate.intercept.FieldInterceptor; 31 import org.hibernate.persister.entity.EntityPersister; 32 import org.hibernate.pretty.MessageHelper; 33 import org.hibernate.type.Type; 34 import org.hibernate.type.TypeFactory; 35 36 41 public abstract class AbstractSaveEventListener extends AbstractReassociateEventListener { 42 43 protected static final int PERSISTENT = 0; 44 protected static final int TRANSIENT = 1; 45 protected static final int DETACHED = 2; 46 protected static final int DELETED = 3; 47 48 private static final Log log = LogFactory.getLog(AbstractSaveEventListener.class); 49 50 58 protected Serializable saveWithRequestedId( 59 Object entity, 60 Serializable requestedId, 61 String entityName, 62 Object anything, 63 EventSource source) 64 throws HibernateException { 65 return performSave( 66 entity, 67 requestedId, 68 source.getEntityPersister(entityName, entity), 69 false, 70 anything, 71 source 72 ); 73 } 74 75 82 protected Serializable saveWithGeneratedId( 83 Object entity, 84 String entityName, 85 Object anything, 86 EventSource source) 87 throws HibernateException { 88 89 EntityPersister persister = source.getEntityPersister(entityName, entity); 90 91 Serializable generatedId = persister.getIdentifierGenerator() 92 .generate( source, entity ); 93 94 if ( generatedId == null ) { 95 throw new IdentifierGenerationException( "null id generated for:" + entity.getClass() ); 96 } 97 else if ( generatedId == IdentifierGeneratorFactory.SHORT_CIRCUIT_INDICATOR ) { 98 return source.getIdentifier( entity ); 99 } 100 else if ( generatedId == IdentifierGeneratorFactory.POST_INSERT_INDICATOR ) { 101 return performSave(entity, null, persister, true, anything, source); 102 } 103 else { 104 105 if ( log.isDebugEnabled() ) { 106 log.debug( 107 "generated identifier: " + 108 persister.getIdentifierType().toLoggableString(generatedId, source.getFactory()) + 109 ", using strategy: " + 110 persister.getIdentifierGenerator().getClass().getName() ); 112 } 113 114 return performSave(entity, generatedId, persister, false, anything, source); 115 } 116 } 117 118 129 protected Serializable performSave( 130 Object entity, 131 Serializable id, 132 EntityPersister persister, 133 boolean useIdentityColumn, 134 Object anything, 135 EventSource source) 136 throws HibernateException { 137 138 if ( log.isTraceEnabled() ) { 139 log.trace( "saving " + MessageHelper.infoString(persister, id, source.getFactory()) ); 140 } 141 142 EntityKey key; 143 if ( !useIdentityColumn ) { 144 key = new EntityKey( id, persister, source.getEntityMode() ); 145 Object old = source.getPersistenceContext().getEntity(key); 146 if (old != null) { 147 if ( source.getPersistenceContext().getEntry(old).getStatus() == Status.DELETED ) { 148 source.forceFlush( source.getPersistenceContext().getEntry(old) ); 149 } 150 else { 151 throw new NonUniqueObjectException( id, persister.getEntityName() ); 152 } 153 } 154 persister.setIdentifier(entity, id, source.getEntityMode()); 155 } 156 else { 157 key = null; 158 } 159 160 if ( invokeSaveLifecycle(entity, persister, source) ) { 161 return id; } 163 164 return performSaveOrReplicate( 165 entity, 166 key, 167 persister, 168 useIdentityColumn, 169 anything, 170 source 171 ); 172 } 173 174 protected boolean invokeSaveLifecycle(Object entity, EntityPersister persister, EventSource source) { 175 if ( persister.implementsLifecycle( source.getEntityMode() ) ) { 178 log.debug( "calling onSave()" ); 179 if ( ( (Lifecycle) entity ).onSave(source) ) { 180 log.debug( "insertion vetoed by onSave()" ); 181 return true; 182 } 183 } 184 return false; 185 } 186 187 protected void validate(Object entity, EntityPersister persister, EventSource source) { 188 if ( persister.implementsValidatable( source.getEntityMode() ) ) { 189 ( ( Validatable ) entity ).validate(); 190 } 191 } 192 193 204 protected Serializable performSaveOrReplicate( 205 Object entity, 206 EntityKey key, 207 EntityPersister persister, 208 boolean useIdentityColumn, 209 Object anything, 210 EventSource source) 211 throws HibernateException { 212 213 validate( entity, persister, source ); 214 215 Serializable id = key==null ? null : key.getIdentifier(); 216 217 if (useIdentityColumn) { 218 log.trace("executing insertions"); 219 source.getActionQueue().executeInserts(); 220 } 221 222 source.getPersistenceContext().addEntry( 226 entity, 227 Status.SAVING, 228 null, 229 null, 230 id, 231 null, 232 LockMode.WRITE, 233 useIdentityColumn, 234 persister, 235 false, 236 false 237 ); 238 239 cascadeBeforeSave(source, persister, entity, anything); 240 241 Object [] values = persister.getPropertyValuesToInsert(entity, getMergeMap(anything), source); 242 Type[] types = persister.getPropertyTypes(); 243 244 boolean substitute = substituteValuesIfNecessary(entity, id, values, persister, source); 245 246 if ( persister.hasCollections() ) { 247 substitute = substitute || visitCollectionsBeforeSave(id, values, types, source); 248 } 249 250 if (substitute) persister.setPropertyValues( entity, values, source.getEntityMode() ); 251 252 TypeFactory.deepCopy( 253 values, 254 types, 255 persister.getPropertyUpdateability(), 256 values, 257 source 258 ); 259 260 new ForeignKeys.Nullifier(entity, false, useIdentityColumn, source) 261 .nullifyTransientReferences(values, types); 262 new Nullability(source).checkNullability( values, persister, false ); 263 264 if (useIdentityColumn) { 265 EntityIdentityInsertAction insert = new EntityIdentityInsertAction(values, entity, persister, source); 266 source.getActionQueue().execute(insert); 267 id = insert.getGeneratedId(); 268 persister.setIdentifier( entity, id, source.getEntityMode() ); 269 key = new EntityKey( id, persister, source.getEntityMode() ); 270 source.getPersistenceContext().checkUniqueness(key, entity); 271 } 273 274 Object version = Versioning.getVersion(values, persister); 275 source.getPersistenceContext().addEntity( 276 entity, 277 Status.MANAGED, 278 values, 279 key, 280 version, 281 LockMode.WRITE, 282 useIdentityColumn, 283 persister, 284 isVersionIncrementDisabled(), 285 false 286 ); 287 289 if ( !useIdentityColumn ) { 290 source.getActionQueue().addAction( 291 new EntityInsertAction(id, values, entity, version, persister, source) 292 ); 293 } 294 295 cascadeAfterSave(source, persister, entity, anything); 296 297 if ( entity instanceof InterceptFieldEnabled ) { 298 FieldInterceptor fieldInterceptor = FieldInterceptor.initFieldInterceptor( 299 entity, 300 persister.getEntityName(), 301 source, 302 null 303 ); 304 fieldInterceptor.dirty(); 305 } 306 307 return id; 308 } 309 310 protected Map getMergeMap(Object anything) { 311 return null; 312 } 313 314 318 protected boolean isVersionIncrementDisabled() { 319 return false; 320 } 321 322 protected boolean visitCollectionsBeforeSave(Serializable id, Object [] values, Type[] types, EventSource source) { 323 WrapVisitor visitor = new WrapVisitor(source); 324 visitor.processEntityPropertyValues(values, types); 326 return visitor.isSubstitutionRequired(); 327 } 328 329 333 protected boolean substituteValuesIfNecessary( 334 Object entity, 335 Serializable id, 336 Object [] values, 337 EntityPersister persister, 338 SessionImplementor source 339 ) { 340 boolean substitute = source.getInterceptor().onSave( 341 entity, 342 id, 343 values, 344 persister.getPropertyNames(), 345 persister.getPropertyTypes() 346 ); 347 348 if ( persister.isVersioned() ) { 350 substitute = Versioning.seedVersion( 351 values, 352 persister.getVersionProperty(), 353 persister.getVersionType() 354 ) || substitute; 355 } 356 return substitute; 357 } 358 359 366 protected void cascadeBeforeSave( 367 EventSource source, 368 EntityPersister persister, 369 Object entity, 370 Object anything) 371 throws HibernateException { 372 373 source.getPersistenceContext().incrementCascadeLevel(); 375 try { 376 new Cascade( getCascadeAction(), Cascade.BEFORE_INSERT_AFTER_DELETE, source ) 377 .cascade(persister, entity, anything); 378 } 379 finally { 380 source.getPersistenceContext().decrementCascadeLevel(); 381 } 382 } 383 384 391 protected void cascadeAfterSave( 392 EventSource source, 393 EntityPersister persister, 394 Object entity, 395 Object anything) 396 throws HibernateException { 397 398 source.getPersistenceContext().incrementCascadeLevel(); 400 try { 401 new Cascade( getCascadeAction(), Cascade.AFTER_INSERT_BEFORE_DELETE, source ) 402 .cascade(persister, entity, anything); 403 } 404 finally { 405 source.getPersistenceContext().decrementCascadeLevel(); 406 } 407 } 408 409 protected abstract CascadingAction getCascadeAction(); 410 411 414 protected int getEntityState( 415 Object entity, 416 String entityName, 417 EntityEntry entry, SessionImplementor source 419 ) { 420 421 if ( entry!=null ) { 423 if ( entry.getStatus() != Status.DELETED ) { 425 if ( log.isTraceEnabled() ) log.trace( "persistent instance of: " + getLoggableName(entityName, entity) ); 427 return PERSISTENT; 428 } 429 else { 430 if ( log.isTraceEnabled() ) log.trace( "deleted instance of: " + getLoggableName(entityName, entity) ); 432 return DELETED; 433 } 434 435 } 436 else { 438 441 if ( ForeignKeys.isTransient( entityName, entity, getAssumedUnsaved(), source ) ) { 442 if ( log.isTraceEnabled() ) log.trace( "transient instance of: " + getLoggableName(entityName, entity) ); 443 return TRANSIENT; 444 } 445 else { 446 if ( log.isTraceEnabled() ) log.trace( "detached instance of: " + getLoggableName(entityName, entity) ); 447 return DETACHED; 448 } 449 450 } 451 } 452 453 private String getLoggableName(String entityName, Object entity) { 454 return entityName==null ? entity.getClass().getName() : entityName; 455 } 456 457 protected Boolean getAssumedUnsaved() { 458 return null; 459 } 460 461 } 462 | Popular Tags |