abstractsaveeventlistener.java

来自「好东西,hibernate-3.2.0,他是一开元的树杖hibernate-3.」· Java 代码 · 共 518 行 · 第 1/2 页

JAVA
518
字号

		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() ) {
			substitute = substitute || visitCollectionsBeforeSave(id, values, types, source);
		}

		if (substitute) persister.setPropertyValues( entity, values, source.getEntityMode() );

		TypeFactory.deepCopy( 
				values, 
				types, 
				persister.getPropertyUpdateability(), 
				values, 
				source
			);
		
		new ForeignKeys.Nullifier(entity, false, useIdentityColumn, source)
				.nullifyTransientReferences(values, types);
		new Nullability(source).checkNullability( values, persister, false );
		
		if ( useIdentityColumn ) {
			EntityIdentityInsertAction insert = new EntityIdentityInsertAction( values, entity, persister, source, shouldDelayIdentityInserts );
			if ( ! shouldDelayIdentityInserts ) {
				log.debug( "executing identity-insert immediately" );
				source.getActionQueue().execute(insert);
				id = insert.getGeneratedId();
				//now done in EntityIdentityInsertAction
				//persister.setIdentifier( entity, id, source.getEntityMode() );
				key = new EntityKey( id, persister, source.getEntityMode() );
				source.getPersistenceContext().checkUniqueness(key, entity);
				//source.getBatcher().executeBatch(); //found another way to ensure that all batched joined inserts have been executed
			}
			else {
				log.debug( "delaying identity-insert due to no transaction in progress" );
				source.getActionQueue().addAction( insert );
				key = insert.getDelayedEntityKey();
			}
		}

		Object version = Versioning.getVersion(values, persister);
		source.getPersistenceContext().addEntity(
				entity,
				Status.MANAGED,
				values,
				key,
				version,
				LockMode.WRITE,
				useIdentityColumn,
				persister,
				isVersionIncrementDisabled(), 
				false
			);
		//source.getPersistenceContext().removeNonExist( new EntityKey( id, persister, source.getEntityMode() ) );

		if ( !useIdentityColumn ) {
			source.getActionQueue().addAction( 
					new EntityInsertAction(id, values, entity, version, persister, source) 
				);
		}

		cascadeAfterSave(source, persister, entity, anything);

		markInterceptorDirty( entity, persister, source );

		return id;
	}

	private void markInterceptorDirty(Object entity, EntityPersister persister, EventSource source) {
		if ( FieldInterceptionHelper.isInstrumented( entity ) ) {
			FieldInterceptor interceptor = FieldInterceptionHelper.injectFieldInterceptor(
					entity, 
					persister.getEntityName(),
					null,
					source
			);
			interceptor.dirty();
		}
	}
	
	protected Map getMergeMap(Object anything) {
		return null;
	}
	
	/**
	 * After the save, will te version number be incremented
	 * if the instance is modified?
	 */
	protected boolean isVersionIncrementDisabled() {
		return false;
	}
	
	protected boolean visitCollectionsBeforeSave(Serializable id, Object[] values, Type[] types, EventSource source) {
		WrapVisitor visitor = new WrapVisitor(source);
		// substitutes into values by side-effect
		visitor.processEntityPropertyValues(values, types);
		return visitor.isSubstitutionRequired();
	}
	
	/**
	 * Perform any property value substitution that is necessary
	 * (interceptor callback, version initialization...)
	 */
	protected boolean substituteValuesIfNecessary(
			Object entity, 
			Serializable id, 
			Object[] values, 
			EntityPersister persister,
			SessionImplementor source
	) {
		boolean substitute = source.getInterceptor().onSave(
				entity,
				id,
				values,
				persister.getPropertyNames(),
				persister.getPropertyTypes()
			);

		//keep the existing version number in the case of replicate!
		if ( persister.isVersioned() ) {
			substitute = Versioning.seedVersion(
					values,
					persister.getVersionProperty(),
					persister.getVersionType(),
			        source
			) || substitute;
		}
		return substitute;
	}

	/**
	 * Handles the calls needed to perform pre-save cascades for the given entity.
	 * @param source The session from whcih the save event originated.
	 * @param persister The entity's persister instance.
	 * @param entity The entity to be saved.
	 * @throws HibernateException
	 */
	protected void cascadeBeforeSave(
			EventSource source,
			EntityPersister persister,
			Object entity,
			Object anything)
	throws HibernateException {

		// cascade-save to many-to-one BEFORE the parent is saved
		source.getPersistenceContext().incrementCascadeLevel();
		try {
			new Cascade( getCascadeAction(), Cascade.BEFORE_INSERT_AFTER_DELETE, source )
					.cascade(persister, entity,	anything);
		}
		finally {
			source.getPersistenceContext().decrementCascadeLevel();
		}
	}

	/**
	 * Handles to calls needed to perform post-save cascades.
	 * @param source The session from which the event originated.
	 * @param persister The entity's persister instance.
	 * @param entity The entity beng saved.
	 * @throws HibernateException
	 */
	protected void cascadeAfterSave(
			EventSource source,
	        EntityPersister persister,
	        Object entity,
			Object anything)
	throws HibernateException {

		// cascade-save to collections AFTER the collection owner was saved
		source.getPersistenceContext().incrementCascadeLevel();
		try {
			new Cascade( getCascadeAction(), Cascade.AFTER_INSERT_BEFORE_DELETE, source )
					.cascade(persister, entity,	anything);
		}
		finally {
			source.getPersistenceContext().decrementCascadeLevel();
		}
	}
	
	protected abstract CascadingAction getCascadeAction();
	
	/**
	 * Determine whether the entity is persistent, detached, or transient
	 */
	protected int getEntityState(
			Object entity, 
			String entityName, 
			EntityEntry entry, //pass this as an argument only to avoid double looking
			SessionImplementor source
	) {
				
		if ( entry!=null ) { // the object is persistent
			
			//the entity is associated with the session, so check its status
			if ( entry.getStatus() != Status.DELETED ) {
				// do nothing for persistent instances
				if ( log.isTraceEnabled() ) {
					log.trace( 
							"persistent instance of: " + 
							getLoggableName(entityName, entity) 
						);
				}
				return PERSISTENT;
			}
			else { 
				//ie. e.status==DELETED
				if ( log.isTraceEnabled() ) {
					log.trace( 
							"deleted instance of: " + 
							getLoggableName(entityName, entity) 
						);
				}
				return DELETED;
			}
			
		}
		else { // the object is transient or detached
			
			//the entity is not associated with the session, so
			//try interceptor and unsaved-value
			
			if ( ForeignKeys.isTransient( entityName, entity, getAssumedUnsaved(), source ) ) {
				if ( log.isTraceEnabled() ) {
					log.trace( 
							"transient instance of: " + 
							getLoggableName(entityName, entity) 
						);
				}
				return TRANSIENT;
			}
			else {
				if ( log.isTraceEnabled() ) {
					log.trace( 
							"detached instance of: " + 
							getLoggableName(entityName, entity) 
						);
				}
				return DETACHED;
			}

		}
	}
	
	protected String getLoggableName(String entityName, Object entity) {
		return entityName==null ? entity.getClass().getName() : entityName;
	}
	
	protected Boolean getAssumedUnsaved() {
		return null;
	}

}

⌨️ 快捷键说明

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