⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractsaveeventlistener.java

📁 一个Java持久层类库
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
//$Id: AbstractSaveEventListener.java 10948 2006-12-07 21:53:10Z steve.ebersole@jboss.com $package org.hibernate.event.def;import java.io.Serializable;import java.util.Map;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.hibernate.LockMode;import org.hibernate.NonUniqueObjectException;import org.hibernate.action.EntityIdentityInsertAction;import org.hibernate.action.EntityInsertAction;import org.hibernate.classic.Lifecycle;import org.hibernate.classic.Validatable;import org.hibernate.engine.Cascade;import org.hibernate.engine.CascadingAction;import org.hibernate.engine.EntityEntry;import org.hibernate.engine.EntityKey;import org.hibernate.engine.ForeignKeys;import org.hibernate.engine.Nullability;import org.hibernate.engine.SessionImplementor;import org.hibernate.engine.Status;import org.hibernate.engine.Versioning;import org.hibernate.event.EventSource;import org.hibernate.id.IdentifierGenerationException;import org.hibernate.id.IdentifierGeneratorFactory;import org.hibernate.intercept.FieldInterceptionHelper;import org.hibernate.intercept.FieldInterceptor;import org.hibernate.persister.entity.EntityPersister;import org.hibernate.pretty.MessageHelper;import org.hibernate.type.Type;import org.hibernate.type.TypeFactory;/** * A convenience bas class for listeners responding to save events. * * @author Steve Ebersole. */public abstract class AbstractSaveEventListener extends AbstractReassociateEventListener {	protected static final int PERSISTENT = 0;	protected static final int TRANSIENT = 1;	protected static final int DETACHED = 2;	protected static final int DELETED = 3;	private static final Logger log = LoggerFactory.getLogger( AbstractSaveEventListener.class );	/**	 * Prepares the save call using the given requested id.	 *	 * @param entity The entity to be saved.	 * @param requestedId The id to which to associate the entity.	 * @param entityName The name of the entity being saved.	 * @param anything Generally cascade-specific information.	 * @param source The session which is the source of this save event.	 *	 * @return The id used to save the entity.	 */	protected Serializable saveWithRequestedId(			Object entity,			Serializable requestedId,			String entityName,			Object anything,			EventSource source) {		return performSave(				entity,				requestedId,				source.getEntityPersister( entityName, entity ),				false,				anything,				source,				true		);	}	/**	 * Prepares the save call using a newly generated id.	 *	 * @param entity The entity to be saved	 * @param entityName The entity-name for the entity to be saved	 * @param anything Generally cascade-specific information.	 * @param source The session which is the source of this save event.	 * @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 saveWithGeneratedId(			Object entity,			String entityName,			Object anything,			EventSource source,			boolean requiresImmediateIdAccess) {		EntityPersister persister = source.getEntityPersister( entityName, entity );		Serializable generatedId = persister.getIdentifierGenerator().generate( source, entity );		if ( generatedId == null ) {			throw new IdentifierGenerationException( "null id generated for:" + entity.getClass() );		}		else if ( generatedId == IdentifierGeneratorFactory.SHORT_CIRCUIT_INDICATOR ) {			return source.getIdentifier( entity );		}		else if ( generatedId == IdentifierGeneratorFactory.POST_INSERT_INDICATOR ) {			return performSave( entity, null, persister, true, anything, source, requiresImmediateIdAccess );		}		else {			if ( log.isDebugEnabled() ) {				log.debug(						"generated identifier: " +								persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ) +								", using strategy: " +								persister.getIdentifierGenerator().getClass().getName()						//TODO: define toString()s for generators				);			}			return performSave( entity, generatedId, persister, false, anything, source, true );		}	}	/**	 * 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		);	}	protected boolean invokeSaveLifecycle(Object entity, EntityPersister persister, EventSource source) {		// Sub-insertions should occur before containing insertion so		// Try to do the callback now		if ( persister.implementsLifecycle( source.getEntityMode() ) ) {			log.debug( "calling onSave()" );			if ( ( ( Lifecycle ) entity ).onSave( source ) ) {				log.debug( "insertion vetoed by onSave()" );				return true;			}		}		return false;	}	protected void validate(Object entity, EntityPersister persister, EventSource source) {		if ( persister.implementsValidatable( source.getEntityMode() ) ) {			( ( Validatable ) entity ).validate();		}	}	/**	 * Performs all the actual work needed to save an entity (well to get the save moved to	 * the execution queue).	 *	 * @param entity The entity to be saved	 * @param key The id to be used for saving the entity (or null, in the case of identity columns)	 * @param persister The entity's persister instance.	 * @param useIdentityColumn Should an identity column be used for id generation?	 * @param anything Generally cascade-specific information.	 * @param source The session which is the source of the current event.	 * @param requiresImmediateIdAccess Is access to the identifier required immediately	 * after the completion of the save?  persist(), for example, does not require this...	 *	 * @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 performSaveOrReplicate(			Object entity,			EntityKey key,			EntityPersister persister,			boolean useIdentityColumn,			Object anything,			EventSource source,			boolean requiresImmediateIdAccess) {		validate( entity, persister, source );		Serializable id = key == null ? null : key.getIdentifier();		boolean inTxn = source.getJDBCContext().isTransactionInProgress();		boolean shouldDelayIdentityInserts = !inTxn && !requiresImmediateIdAccess;		if ( useIdentityColumn && !shouldDelayIdentityInserts ) {			log.trace( "executing insertions" );			source.getActionQueue().executeInserts();		}		// Put a placeholder in entries, so we don't recurse back and try to save() the		// same object again. QUESTION: should this be done before onSave() is called?		// likewise, should it be done before onUpdate()?		source.getPersistenceContext().addEntry(				entity,				Status.SAVING,				null,				null,				id,				null,				LockMode.WRITE,				useIdentityColumn,				persister,				false,				false		);		cascadeBeforeSave( source, persister, entity, anything );		Object[] values = persister.getPropertyValuesToInsert( entity, getMergeMap( anything ), source );		Type[] types = persister.getPropertyTypes();		boolean substitute = substituteValuesIfNecessary( entity, id, values, persister, source );		if ( persister.hasCollections() ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -