Java Code Examples for org.hibernate.event.EventSource#getEntityMode()

The following examples show how to use org.hibernate.event.EventSource#getEntityMode() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DefaultMergeEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 6 votes vote down vote up
private boolean existsInDatabase(Object entity, EventSource source, EntityPersister persister) {
	EntityEntry entry = source.getPersistenceContext().getEntry( entity );
	if ( entry == null ) {
		Serializable id = persister.getIdentifier( entity, source.getEntityMode() );
		if ( id != null ) {
			EntityKey key = new EntityKey( id, persister, source.getEntityMode() );
			Object managedEntity = source.getPersistenceContext().getEntity( key );
			entry = source.getPersistenceContext().getEntry( managedEntity );
		}
	}

	if ( entry == null ) {
		// perhaps this should be an exception since it is only ever used
		// in the above method?
		return false;
	}
	else {
		return entry.isExistsInDatabase();
	}
}
 
Example 2
Source File: DefaultFlushEntityEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
/**
 * Flushes a single entity's state to the database, by scheduling
 * an update action, if necessary
 */
public void onFlushEntity(FlushEntityEvent event) throws HibernateException {
	final Object entity = event.getEntity();
	final EntityEntry entry = event.getEntityEntry();
	final EventSource session = event.getSession();
	final EntityPersister persister = entry.getPersister();
	final Status status = entry.getStatus();
	final EntityMode entityMode = session.getEntityMode();
	final Type[] types = persister.getPropertyTypes();

	final boolean mightBeDirty = entry.requiresDirtyCheck(entity);

	final Object[] values = getValues( entity, entry, entityMode, mightBeDirty, session );

	event.setPropertyValues(values);

	//TODO: avoid this for non-new instances where mightBeDirty==false
	boolean substitute = wrapCollections( session, persister, types, values);

	if ( isUpdateNecessary( event, mightBeDirty ) ) {
		substitute = scheduleUpdate( event ) || substitute;
	}

	if ( status != Status.DELETED ) {
		// now update the object .. has to be outside the main if block above (because of collections)
		if (substitute) persister.setPropertyValues( entity, values, entityMode );

		// Search for collections by reachability, updating their role.
		// We don't want to touch collections reachable from a deleted object
		if ( persister.hasCollections() ) {
			new FlushVisitor(session, entity).processEntityPropertyValues(values, types);
		}
	}

}
 
Example 3
Source File: DefaultDeleteEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 4 votes vote down vote up
/**
 * 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;
		}
		else {
			performDetachedEntityDeletionCheck( event );
		}

		id = persister.getIdentifier( entity, source.getEntityMode() );

		if ( id == null ) {
			throw new TransientObjectException(
					"the detached instance passed to delete() had a null identifier"
			);
		}

		EntityKey key = new EntityKey( id, persister, source.getEntityMode() );

		persistenceContext.checkUniqueness( key, entity );

		new OnUpdateVisitor( source, id, entity ).process( entity, persister );

		version = persister.getVersion( entity, source.getEntityMode() );

		entityEntry = persistenceContext.addEntity(
				entity,
				Status.MANAGED,
				persister.getPropertyValues( entity, source.getEntityMode() ),
				key,
				version,
				LockMode.NONE,
				true,
				persister,
				false,
				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(), persister, transientEntities );

	if ( source.getFactory().getSettings().isIdentifierRollbackEnabled() ) {
		persister.resetIdentifier( entity, id, version, source.getEntityMode() );
	}
}
 
Example 4
Source File: DefaultDeleteEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 4 votes vote down vote up
/**
 * Perform the entity deletion.  Well, as with most operations, does not
 * really perform it; just schedules an action/execution with the
 * {@link org.hibernate.engine.ActionQueue} for execution during flush.
 *
 * @param session The originating session
 * @param entity The entity to delete
 * @param entityEntry The entity's entry in the {@link PersistenceContext}
 * @param isCascadeDeleteEnabled Is delete cascading enabled?
 * @param persister The entity persister.
 * @param transientEntities A cache of already deleted entities.
 */
protected final void deleteEntity(
		final EventSource session,
		final Object entity,
		final EntityEntry entityEntry,
		final boolean isCascadeDeleteEnabled,
		final EntityPersister persister,
		final Set transientEntities) {

	if ( log.isTraceEnabled() ) {
		log.trace(
				"deleting " +
						MessageHelper.infoString( persister, entityEntry.getId(), session.getFactory() )
		);
	}

	final PersistenceContext persistenceContext = session.getPersistenceContext();
	final Type[] propTypes = persister.getPropertyTypes();
	final Object version = entityEntry.getVersion();

	final Object[] currentState;
	if ( entityEntry.getLoadedState() == null ) { //ie. the entity came in from update()
		currentState = persister.getPropertyValues( entity, session.getEntityMode() );
	}
	else {
		currentState = entityEntry.getLoadedState();
	}

	final Object[] deletedState = createDeletedState( persister, currentState, session );
	entityEntry.setDeletedState( deletedState );

	session.getInterceptor().onDelete(
			entity,
			entityEntry.getId(),
			deletedState,
			persister.getPropertyNames(),
			propTypes
	);

	// before any callbacks, etc, so subdeletions see that this deletion happened first
	persistenceContext.setEntryStatus( entityEntry, Status.DELETED );
	EntityKey key = new EntityKey( entityEntry.getId(), persister, session.getEntityMode() );

	cascadeBeforeDelete( session, persister, entity, entityEntry, transientEntities );

	new ForeignKeys.Nullifier( entity, true, false, session )
			.nullifyTransientReferences( entityEntry.getDeletedState(), propTypes );
	new Nullability( session ).checkNullability( entityEntry.getDeletedState(), persister, true );
	persistenceContext.getNullifiableEntityKeys().add( key );

	// Ensures that containing deletions happen before sub-deletions
	session.getActionQueue().addAction(
			new EntityDeleteAction(
					entityEntry.getId(),
					deletedState,
					version,
					entity,
					persister,
					isCascadeDeleteEnabled,
					session
			)
	);

	cascadeAfterDelete( session, persister, entity, transientEntities );

	// the entry will be removed after the flush, and will no longer
	// override the stale snapshot
	// This is now handled by removeEntity() in EntityDeleteAction
	//persistenceContext.removeDatabaseSnapshot(key);
}
 
Example 5
Source File: DefaultFlushEntityEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 4 votes vote down vote up
private boolean scheduleUpdate(final FlushEntityEvent event) {
	
	final EntityEntry entry = event.getEntityEntry();
	final EventSource session = event.getSession();
	final Object entity = event.getEntity();
	final Status status = entry.getStatus();
	final EntityMode entityMode = session.getEntityMode();
	final EntityPersister persister = entry.getPersister();
	final Object[] values = event.getPropertyValues();
	
	if ( log.isTraceEnabled() ) {
		if ( status == Status.DELETED ) {
			log.trace(
					"Updating deleted entity: " +
					MessageHelper.infoString( persister, entry.getId(), session.getFactory() )
				);
		}
		else {
			log.trace(
					"Updating entity: " +
					MessageHelper.infoString( persister, entry.getId(), session.getFactory()  )
				);
		}
	}

	boolean intercepted;
	
	if ( !entry.isBeingReplicated() ) {
		// give the Interceptor a chance to process property values, if the properties 
		// were modified by the Interceptor, we need to set them back to the object
		intercepted = handleInterception( event );
	}
	else {
		intercepted = false;
	}

	validate( entity, persister, status, entityMode );

	// increment the version number (if necessary)
	final Object nextVersion = getNextVersion(event);

	// if it was dirtied by a collection only
	int[] dirtyProperties = event.getDirtyProperties();
	if ( event.isDirtyCheckPossible() && dirtyProperties == null ) {
		if ( ! intercepted && !event.hasDirtyCollection() ) {
			throw new AssertionFailure( "dirty, but no dirty properties" );
		}
		dirtyProperties = ArrayHelper.EMPTY_INT_ARRAY;
	}

	// check nullability but do not perform command execute
	// we'll use scheduled updates for that.
	new Nullability(session).checkNullability( values, persister, true );

	// schedule the update
	// note that we intentionally do _not_ pass in currentPersistentState!
	session.getActionQueue().addAction(
			new EntityUpdateAction(
					entry.getId(),
					values,
					dirtyProperties,
					event.hasDirtyCollection(),
					entry.getLoadedState(),
					entry.getVersion(),
					nextVersion,
					entity,
					entry.getRowId(),
					persister,
					session
				)
		);
	
	return intercepted;
}
 
Example 6
Source File: DefaultSaveOrUpdateEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 4 votes vote down vote up
protected void performUpdate(
		SaveOrUpdateEvent event,
		Object entity,
		EntityPersister persister) throws HibernateException {

	if ( !persister.isMutable() ) {
		log.trace( "immutable instance passed to doUpdate(), locking" );
		reassociate( event, entity, event.getRequestedId(), persister );
	}
	else {

		if ( log.isTraceEnabled() ) {
			log.trace(
					"updating " +
							MessageHelper.infoString(
									persister, event.getRequestedId(), event.getSession().getFactory()
							)
			);
		}

		final EventSource source = event.getSession();

		EntityKey key = new EntityKey( event.getRequestedId(), persister, source.getEntityMode() );

		source.getPersistenceContext().checkUniqueness( key, entity );

		if ( invokeUpdateLifecycle( entity, persister, source ) ) {
			reassociate( event, event.getObject(), event.getRequestedId(), persister );
			return;
		}

		// this is a transient object with existing persistent state not loaded by the session

		new OnUpdateVisitor( source, event.getRequestedId(), entity ).process( entity, persister );

		//TODO: put this stuff back in to read snapshot from
		//      the second-level cache (needs some extra work)
		/*Object[] cachedState = null;

		if ( persister.hasCache() ) {
			CacheEntry entry = (CacheEntry) persister.getCache()
					.get( event.getRequestedId(), source.getTimestamp() );
		    cachedState = entry==null ? 
		    		null : 
		    		entry.getState(); //TODO: half-assemble this stuff
		}*/

		source.getPersistenceContext().addEntity(
				entity,
				Status.MANAGED,
				null, //cachedState,
				key,
				persister.getVersion( entity, source.getEntityMode() ),
				LockMode.NONE,
				true,
				persister,
				false,
				true //assume true, since we don't really know, and it doesn't matter
		);

		persister.afterReassociate( entity, source );

		if ( log.isTraceEnabled() ) {
			log.trace(
					"updating " +
							MessageHelper.infoString( persister, event.getRequestedId(), source.getFactory() )
			);
		}

		cascadeOnUpdate( event, persister, entity );

	}
}
 
Example 7
Source File: DefaultReplicateEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 4 votes vote down vote up
/**
 * Handle the given replicate event.
 *
 * @param event The replicate event to be handled.
 *
 * @throws TransientObjectException An invalid attempt to replicate a transient entity.
 */
public void onReplicate(ReplicateEvent event) {
	final EventSource source = event.getSession();
	if ( source.getPersistenceContext().reassociateIfUninitializedProxy( event.getObject() ) ) {
		log.trace( "uninitialized proxy passed to replicate()" );
		return;
	}

	Object entity = source.getPersistenceContext().unproxyAndReassociate( event.getObject() );

	if ( source.getPersistenceContext().isEntryFor( entity ) ) {
		log.trace( "ignoring persistent instance passed to replicate()" );
		//hum ... should we cascade anyway? throw an exception? fine like it is?
		return;
	}

	EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );

	// get the id from the object
	/*if ( persister.isUnsaved(entity, source) ) {
		throw new TransientObjectException("transient instance passed to replicate()");
	}*/
	Serializable id = persister.getIdentifier( entity, source.getEntityMode() );
	if ( id == null ) {
		throw new TransientObjectException( "instance with null id passed to replicate()" );
	}

	final ReplicationMode replicationMode = event.getReplicationMode();

	final Object oldVersion;
	if ( replicationMode == ReplicationMode.EXCEPTION ) {
		//always do an INSERT, and let it fail by constraint violation
		oldVersion = null;
	}
	else {
		//what is the version on the database?
		oldVersion = persister.getCurrentVersion( id, source );			
	}

	if ( oldVersion != null ) { 			
		if ( log.isTraceEnabled() ) {
			log.trace(
					"found existing row for " +
							MessageHelper.infoString( persister, id, source.getFactory() )
			);
		}

		/// HHH-2378
		final Object realOldVersion = persister.isVersioned() ? oldVersion : null;
		
		boolean canReplicate = replicationMode.shouldOverwriteCurrentVersion(
				entity,
				realOldVersion,
				persister.getVersion( entity, source.getEntityMode() ),
				persister.getVersionType()
		);

		if ( canReplicate ) {
			//will result in a SQL UPDATE:
			performReplication( entity, id, realOldVersion, persister, replicationMode, source );
		}
		else {
			//else do nothing (don't even reassociate object!)
			log.trace( "no need to replicate" );
		}

		//TODO: would it be better to do a refresh from db?
	}
	else {
		// no existing row - do an insert
		if ( log.isTraceEnabled() ) {
			log.trace(
					"no existing row, replicating new instance " +
							MessageHelper.infoString( persister, id, source.getFactory() )
			);
		}

		final boolean regenerate = persister.isIdentifierAssignedByInsert(); // prefer re-generation of identity!
		final EntityKey key = regenerate ?
				null : new EntityKey( id, persister, source.getEntityMode() );

		performSaveOrReplicate(
				entity,
				key,
				persister,
				regenerate,
				replicationMode,
				source,
				true
		);

	}
}
 
Example 8
Source File: AbstractReassociateEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 4 votes vote down vote up
/**
 * Associates a given entity (either transient or associated with another session) to
 * the given session.
 *
 * @param event The event triggering the re-association
 * @param object The entity to be associated
 * @param id The id of the entity.
 * @param persister The entity's persister instance.
 *
 * @return An EntityEntry representing the entity within this session.
 */
protected final EntityEntry reassociate(AbstractEvent event, Object object, Serializable id, EntityPersister persister) {

	if ( log.isTraceEnabled() ) {
		log.trace(
				"reassociating transient instance: " +
						MessageHelper.infoString( persister, id, event.getSession().getFactory() )
		);
	}

	EventSource source = event.getSession();
	EntityKey key = new EntityKey( id, persister, source.getEntityMode() );

	source.getPersistenceContext().checkUniqueness( key, object );

	//get a snapshot
	Object[] values = persister.getPropertyValues( object, source.getEntityMode() );
	TypeFactory.deepCopy(
			values,
			persister.getPropertyTypes(),
			persister.getPropertyUpdateability(),
			values,
			source
	);
	Object version = Versioning.getVersion( values, persister );

	EntityEntry newEntry = source.getPersistenceContext().addEntity(
			object,
			Status.MANAGED,
			values,
			key,
			version,
			LockMode.NONE,
			true,
			persister,
			false,
			true //will be ignored, using the existing Entry instead
	);

	new OnLockVisitor( source, id, object ).process( object, persister );

	persister.afterReassociate( object, source );

	return newEntry;

}
 
Example 9
Source File: DefaultMergeEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 4 votes vote down vote up
/** 
 * Handle the given merge event.
 *
 * @param event The merge event to be handled.
 * @throws HibernateException
 */
public void onMerge(MergeEvent event, Map copyCache) throws HibernateException {

	final EventSource source = event.getSession();
	final Object original = event.getOriginal();

	if ( original != null ) {

		final Object entity;
		if ( original instanceof HibernateProxy ) {
			LazyInitializer li = ( (HibernateProxy) original ).getHibernateLazyInitializer();
			if ( li.isUninitialized() ) {
				log.trace("ignoring uninitialized proxy");
				event.setResult( source.load( li.getEntityName(), li.getIdentifier() ) );
				return; //EARLY EXIT!
			}
			else {
				entity = li.getImplementation();
			}
		}
		else {
			entity = original;
		}
		
		if ( copyCache.containsKey(entity) ) {
			log.trace("already merged");
			event.setResult(entity);
		}
		else {
			event.setEntity( entity );
			int entityState = -1;

			// Check the persistence context for an entry relating to this
			// entity to be merged...
			EntityEntry entry = source.getPersistenceContext().getEntry( entity );
			if ( entry == null ) {
				EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
				Serializable id = persister.getIdentifier( entity, source.getEntityMode() );
				if ( id != null ) {
					EntityKey key = new EntityKey( id, persister, source.getEntityMode() );
					Object managedEntity = source.getPersistenceContext().getEntity( key );
					entry = source.getPersistenceContext().getEntry( managedEntity );
					if ( entry != null ) {
						// we have specialized case of a detached entity from the
						// perspective of the merge operation.  Specifically, we
						// have an incoming entity instance which has a corresponding
						// entry in the current persistence context, but registered
						// under a different entity instance
						entityState = DETACHED;
					}
				}
			}

			if ( entityState == -1 ) {
				entityState = getEntityState( entity, event.getEntityName(), entry, source );
			}
			
			switch (entityState) {
				case DETACHED:
					entityIsDetached(event, copyCache);
					break;
				case TRANSIENT:
					entityIsTransient(event, copyCache);
					break;
				case PERSISTENT:
					entityIsPersistent(event, copyCache);
					break;
				default: //DELETED
					throw new ObjectDeletedException( 
							"deleted instance passed to merge", 
							null, 
							getLoggableName( event.getEntityName(), entity )
						);			
			}
		}
		
	}
	
}
 
Example 10
Source File: AbstractSaveEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 4 votes vote down vote up
/**
 * Ppepares the save call by checking the session caches for a pre-existing
 * entity and performing any lifecycle callbacks.
 *
 * @param entity The entity to be saved.
 * @param id The id by which to save the entity.
 * @param persister The entity's persister instance.
 * @param useIdentityColumn Is an identity column being used?
 * @param anything Generally cascade-specific information.
 * @param source The session from which the event originated.
 * @param requiresImmediateIdAccess does the event context require
 * access to the identifier immediately after execution of this method (if
 * not, post-insert style id generators may be postponed if we are outside
 * a transaction).
 *
 * @return The id used to save the entity; may be null depending on the
 *         type of id generator used and the requiresImmediateIdAccess value
 */
protected Serializable performSave(
		Object entity,
		Serializable id,
		EntityPersister persister,
		boolean useIdentityColumn,
		Object anything,
		EventSource source,
		boolean requiresImmediateIdAccess) {

	if ( log.isTraceEnabled() ) {
		log.trace(
				"saving " +
						MessageHelper.infoString( persister, id, source.getFactory() )
		);
	}

	EntityKey key;
	if ( !useIdentityColumn ) {
		key = new EntityKey( id, persister, source.getEntityMode() );
		Object old = source.getPersistenceContext().getEntity( key );
		if ( old != null ) {
			if ( source.getPersistenceContext().getEntry( old ).getStatus() == Status.DELETED ) {
				source.forceFlush( source.getPersistenceContext().getEntry( old ) );
			}
			else {
				throw new NonUniqueObjectException( id, persister.getEntityName() );
			}
		}
		persister.setIdentifier( entity, id, source.getEntityMode() );
	}
	else {
		key = null;
	}

	if ( invokeSaveLifecycle( entity, persister, source ) ) {
		return id; //EARLY EXIT
	}

	return performSaveOrReplicate(
			entity,
			key,
			persister,
			useIdentityColumn,
			anything,
			source,
			requiresImmediateIdAccess
	);
}