/** * Handle the given lock event. * * @param event The lock event to be handled. * @throws HibernateException */ public void onLock(LockEvent event) throws HibernateException { if (event.getObject() == null) { throw new NullPointerException("attempted to lock null"); } if (event.getLockMode() == LockMode.WRITE) { throw new HibernateException("Invalid lock mode for lock()"); } SessionImplementor source = event.getSession(); Object entity = source.getPersistenceContext().unproxyAndReassociate(event.getObject()); // TODO: if object was an uninitialized proxy, this is inefficient, // resulting in two SQL selects EntityEntry entry = source.getPersistenceContext().getEntry(entity); if (entry == null) { final EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity); final Serializable id = persister.getIdentifier(entity, source.getEntityMode()); if (!ForeignKeys.isNotTransient(event.getEntityName(), entity, Boolean.FALSE, source)) { throw new TransientObjectException( "cannot lock an unsaved transient instance: " + persister.getEntityName()); } entry = reassociate(event, entity, id, persister); cascadeOnLock(event, persister, entity); } upgradeLock(entity, entry, event.getLockMode(), source); }
/** make sure user didn't mangle the id */ public void checkId( Object object, EntityPersister persister, Serializable id, EntityMode entityMode, SessionImplementor session) throws HibernateException { if (id != null && id instanceof DelayedPostInsertIdentifier) { // this is a situation where the entity id is assigned by a post-insert generator // and was saved outside the transaction forcing it to be delayed return; } if (persister.canExtractIdOutOfEntity()) { Serializable oid = persister.getIdentifier(object, session); if (id == null) { throw new AssertionFailure( "null id in " + persister.getEntityName() + " entry (don't flush the Session after an exception occurs)"); } if (!persister.getIdentifierType().isEqual(id, oid, entityMode, session.getFactory())) { throw new HibernateException( "identifier of an instance of " + persister.getEntityName() + " was altered from " + id + " to " + oid); } } }
/** * Reads the entity hosting the association from the datastore and applies any property changes * from the server side. */ private void updateHostingEntityIfRequired() { if (hostingEntity != null && hostingEntityRequiresReadAfterUpdate()) { EntityPersister entityPersister = getHostingEntityPersister(); entityPersister.processUpdateGeneratedProperties( entityPersister.getIdentifier(hostingEntity, session), hostingEntity, new Object[entityPersister.getPropertyNames().length], session); } }
/** * Determine the id to use for updating. * * @param entity The entity. * @param persister The entity persister * @param requestedId The requested identifier * @param session The session * @return The id. * @throws TransientObjectException If the entity is considered transient. */ protected Serializable getUpdateId( Object entity, EntityPersister persister, Serializable requestedId, SessionImplementor session) { // use the id assigned to the instance Serializable id = persister.getIdentifier(entity, session); if (id == null) { // assume this is a newly instantiated transient object // which should be saved rather than updated throw new TransientObjectException( "The given object has a null identifier: " + persister.getEntityName()); } else { return id; } }
/** * Handle the given delete event. This is the cascaded form. * * @param event The delete event. * @param transientEntities The cache of entities already deleted * @throws HibernateException */ public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException { final EventSource source = event.getSession(); final PersistenceContext persistenceContext = source.getPersistenceContext(); Object entity = persistenceContext.unproxyAndReassociate(event.getObject()); EntityEntry entityEntry = persistenceContext.getEntry(entity); final EntityPersister persister; final Serializable id; final Object version; if (entityEntry == null) { LOG.trace("Entity was not persistent in delete processing"); persister = source.getEntityPersister(event.getEntityName(), entity); if (ForeignKeys.isTransient(persister.getEntityName(), entity, null, source)) { deleteTransientEntity( source, entity, event.isCascadeDeleteEnabled(), persister, transientEntities); // EARLY EXIT!!! return; } performDetachedEntityDeletionCheck(event); id = persister.getIdentifier(entity, source); if (id == null) { throw new TransientObjectException( "the detached instance passed to delete() had a null identifier"); } final EntityKey key = source.generateEntityKey(id, persister); persistenceContext.checkUniqueness(key, entity); new OnUpdateVisitor(source, id, entity).process(entity, persister); version = persister.getVersion(entity); entityEntry = persistenceContext.addEntity( entity, (persister.isMutable() ? Status.MANAGED : Status.READ_ONLY), persister.getPropertyValues(entity), key, version, LockMode.NONE, true, persister, false); } else { LOG.trace("Deleting a persistent instance"); if (entityEntry.getStatus() == Status.DELETED || entityEntry.getStatus() == Status.GONE) { LOG.trace("Object was already deleted"); return; } persister = entityEntry.getPersister(); id = entityEntry.getId(); version = entityEntry.getVersion(); } /*if ( !persister.isMutable() ) { throw new HibernateException( "attempted to delete an object of immutable class: " + MessageHelper.infoString(persister) ); }*/ if (invokeDeleteLifecycle(source, entity, persister)) { return; } deleteEntity( source, entity, entityEntry, event.isCascadeDeleteEnabled(), event.isOrphanRemovalBeforeUpdates(), persister, transientEntities); if (source.getFactory().getSettings().isIdentifierRollbackEnabled()) { persister.resetIdentifier(entity, id, version, source); } }