[hibernate-commits] Hibernate SVN: r10949 - in branches/Branch_3_2/Hibernate3: src/org/hibernate/event/def test/org/hibernate/test/propertyref/basic

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Dec 7 16:53:48 EST 2006


Author: steve.ebersole at jboss.com
Date: 2006-12-07 16:53:41 -0500 (Thu, 07 Dec 2006)
New Revision: 10949

Modified:
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.java
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java
Log:
HHH-2291 - reattachment of collections with a property-ref key;
code and javadoc cleanup

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractReassociateEventListener.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -5,7 +5,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.hibernate.HibernateException;
+
 import org.hibernate.LockMode;
 import org.hibernate.engine.EntityEntry;
 import org.hibernate.engine.EntityKey;
@@ -25,7 +25,7 @@
  */
 public class AbstractReassociateEventListener implements Serializable {
 
-	private static final Log log = LogFactory.getLog(AbstractReassociateEventListener.class);
+	private static final Log log = LogFactory.getLog( AbstractReassociateEventListener.class );
 
 	/**
 	 * Associates a given entity (either transient or associated with another session) to
@@ -35,52 +35,53 @@
 	 * @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.
-	 * @throws HibernateException
 	 */
-	protected final EntityEntry reassociate(AbstractEvent event, Object object, Serializable id, EntityPersister persister)
-	throws HibernateException {
-		
-		if ( log.isTraceEnabled() ) log.trace(
-				"reassociating transient instance: " +
-				MessageHelper.infoString( persister, id, event.getSession().getFactory() )
+	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);
-		
+
+		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);
-		
+		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, 
+				object,
+				Status.MANAGED,
+				values,
+				key,
+				version,
+				LockMode.NONE,
+				true,
+				persister,
+				false,
 				true //will be ignored, using the existing Entry instead
-			);
-		
-		new OnLockVisitor( source, id ).process( object, persister );
-		
+		);
+
+		new OnLockVisitor( source, id, object ).process( object, persister );
+
 		persister.afterReassociate( object, source );
-		
+
 		return newEntry;
-		
+
 	}
 
 }

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/AbstractSaveEventListener.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -6,7 +6,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.hibernate.HibernateException;
+
 import org.hibernate.LockMode;
 import org.hibernate.NonUniqueObjectException;
 import org.hibernate.action.EntityIdentityInsertAction;
@@ -44,60 +44,59 @@
 	protected static final int DETACHED = 2;
 	protected static final int DELETED = 3;
 
-	private static final Log log = LogFactory.getLog(AbstractSaveEventListener.class);
+	private static final Log log = LogFactory.getLog( 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.
-	 * @throws HibernateException
 	 */
 	protected Serializable saveWithRequestedId(
 			Object entity,
 			Serializable requestedId,
 			String entityName,
 			Object anything,
-			EventSource source) 
-	throws HibernateException {
+			EventSource source) {
 		return performSave(
 				entity,
 				requestedId,
-				source.getEntityPersister(entityName, entity),
+				source.getEntityPersister( entityName, entity ),
 				false,
 				anything,
 				source,
-		        true
-			);
+				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
-	 * @throws HibernateException
+	 *         type of id generator used and the requiresImmediateIdAccess value
 	 */
 	protected Serializable saveWithGeneratedId(
 			Object entity,
 			String entityName,
 			Object anything,
 			EventSource source,
-	        boolean requiresImmediateIdAccess)
-	throws HibernateException {
-		
-		EntityPersister persister = source.getEntityPersister(entityName, entity);
-
-		Serializable generatedId = persister.getIdentifierGenerator()
-			.generate( source, entity );
-		
+			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() );
 		}
@@ -108,16 +107,17 @@
 			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
-					);
+						"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 );
 		}
 	}
@@ -125,18 +125,20 @@
 	/**
 	 * 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 in use?
+	 * @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
-	 * @throws HibernateException
+	 *         type of id generator used and the requiresImmediateIdAccess value
 	 */
 	protected Serializable performSave(
 			Object entity,
@@ -145,55 +147,54 @@
 			boolean useIdentityColumn,
 			Object anything,
 			EventSource source,
-	        boolean requiresImmediateIdAccess)
-	throws HibernateException {
+			boolean requiresImmediateIdAccess) {
 
 		if ( log.isTraceEnabled() ) {
-			log.trace( 
-					"saving " + 
-					MessageHelper.infoString( persister, id, source.getFactory() ) 
-				);
+			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) );
+			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());
+			persister.setIdentifier( entity, id, source.getEntityMode() );
 		}
 		else {
 			key = null;
 		}
-		
-		if ( invokeSaveLifecycle(entity, persister, source) ) {
+
+		if ( invokeSaveLifecycle( entity, persister, source ) ) {
 			return id; //EARLY EXIT
 		}
 
 		return performSaveOrReplicate(
-				entity, 
-				key, 
-				persister, 
-				useIdentityColumn, 
-				anything, 
+				entity,
+				key,
+				persister,
+				useIdentityColumn,
+				anything,
 				source,
-		        requiresImmediateIdAccess
-			);
+				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) ) {
+			if ( ( ( Lifecycle ) entity ).onSave( source ) ) {
 				log.debug( "insertion vetoed by onSave()" );
 				return true;
 			}
@@ -203,21 +204,25 @@
 
 	protected void validate(Object entity, EntityPersister persister, EventSource source) {
 		if ( persister.implementsValidatable( source.getEntityMode() ) ) {
-            ( ( Validatable ) entity ).validate();
-        }
+			( ( 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
-	 * @throws HibernateException
+	 *         type of id generator used and the requiresImmediateIdAccess value
 	 */
 	protected Serializable performSaveOrReplicate(
 			Object entity,
@@ -226,18 +231,17 @@
 			boolean useIdentityColumn,
 			Object anything,
 			EventSource source,
-	        boolean requiresImmediateIdAccess)
-	throws HibernateException {
-		
+			boolean requiresImmediateIdAccess) {
+
 		validate( entity, persister, source );
 
-		Serializable id = key==null ? null : key.getIdentifier();
+		Serializable id = key == null ? null : key.getIdentifier();
 
 		boolean inTxn = source.getJDBCContext().isTransactionInProgress();
 		boolean shouldDelayIdentityInserts = !inTxn && !requiresImmediateIdAccess;
 
 		if ( useIdentityColumn && !shouldDelayIdentityInserts ) {
-			log.trace("executing insertions");
+			log.trace( "executing insertions" );
 			source.getActionQueue().executeInserts();
 		}
 
@@ -253,46 +257,50 @@
 				null,
 				LockMode.WRITE,
 				useIdentityColumn,
-				persister, 
-				false, 
+				persister,
+				false,
 				false
-			);
+		);
 
-		cascadeBeforeSave(source, persister, entity, anything);
+		cascadeBeforeSave( source, persister, entity, anything );
 
-		Object[] values = persister.getPropertyValuesToInsert(entity, getMergeMap(anything), source);
+		Object[] values = persister.getPropertyValuesToInsert( entity, getMergeMap( anything ), source );
 		Type[] types = persister.getPropertyTypes();
 
-		boolean substitute = substituteValuesIfNecessary(entity, id, values, persister, source);
+		boolean substitute = substituteValuesIfNecessary( entity, id, values, persister, source );
 
 		if ( persister.hasCollections() ) {
-			substitute = substitute || visitCollectionsBeforeSave(id, values, types, source);
+			substitute = substitute || visitCollectionsBeforeSave( entity, id, values, types, source );
 		}
 
-		if (substitute) persister.setPropertyValues( entity, values, source.getEntityMode() );
+		if ( substitute ) {
+			persister.setPropertyValues( entity, values, source.getEntityMode() );
+		}
 
-		TypeFactory.deepCopy( 
-				values, 
-				types, 
-				persister.getPropertyUpdateability(), 
-				values, 
+		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
 			);
-		
-		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 ) {
+			if ( !shouldDelayIdentityInserts ) {
 				log.debug( "executing identity-insert immediately" );
-				source.getActionQueue().execute(insert);
+				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.getPersistenceContext().checkUniqueness( key, entity );
 				//source.getBatcher().executeBatch(); //found another way to ensure that all batched joined inserts have been executed
 			}
 			else {
@@ -302,7 +310,7 @@
 			}
 		}
 
-		Object version = Versioning.getVersion(values, persister);
+		Object version = Versioning.getVersion( values, persister );
 		source.getPersistenceContext().addEntity(
 				entity,
 				Status.MANAGED,
@@ -312,18 +320,18 @@
 				LockMode.WRITE,
 				useIdentityColumn,
 				persister,
-				isVersionIncrementDisabled(), 
+				isVersionIncrementDisabled(),
 				false
-			);
+		);
 		//source.getPersistenceContext().removeNonExist( new EntityKey( id, persister, source.getEntityMode() ) );
 
 		if ( !useIdentityColumn ) {
-			source.getActionQueue().addAction( 
-					new EntityInsertAction(id, values, entity, version, persister, source) 
-				);
+			source.getActionQueue().addAction(
+					new EntityInsertAction( id, values, entity, version, persister, source )
+			);
 		}
 
-		cascadeAfterSave(source, persister, entity, anything);
+		cascadeAfterSave( source, persister, entity, anything );
 
 		markInterceptorDirty( entity, persister, source );
 
@@ -333,7 +341,7 @@
 	private void markInterceptorDirty(Object entity, EntityPersister persister, EventSource source) {
 		if ( FieldInterceptionHelper.isInstrumented( entity ) ) {
 			FieldInterceptor interceptor = FieldInterceptionHelper.injectFieldInterceptor(
-					entity, 
+					entity,
 					persister.getEntityName(),
 					null,
 					source
@@ -341,44 +349,55 @@
 			interceptor.dirty();
 		}
 	}
-	
+
 	protected Map getMergeMap(Object anything) {
 		return null;
 	}
-	
+
 	/**
 	 * After the save, will te version number be incremented
 	 * if the instance is modified?
+	 *
+	 * @return True if the version will be incremented on an entity change after save;
+	 *         false otherwise.
 	 */
 	protected boolean isVersionIncrementDisabled() {
 		return false;
 	}
-	
-	protected boolean visitCollectionsBeforeSave(Serializable id, Object[] values, Type[] types, EventSource source) {
-		WrapVisitor visitor = new WrapVisitor(source);
+
+	protected boolean visitCollectionsBeforeSave(Object entity, Serializable id, Object[] values, Type[] types, EventSource source) {
+		WrapVisitor visitor = new WrapVisitor( source );
 		// substitutes into values by side-effect
-		visitor.processEntityPropertyValues(values, types);
+		visitor.processEntityPropertyValues( values, types );
 		return visitor.isSubstitutionRequired();
 	}
-	
+
 	/**
 	 * Perform any property value substitution that is necessary
 	 * (interceptor callback, version initialization...)
+	 *
+	 * @param entity The entity
+	 * @param id The entity identifier
+	 * @param values The snapshot entity state
+	 * @param persister The entity persister
+	 * @param source The originating session
+	 *
+	 * @return True if the snapshot state changed such that
+	 * reinjection of the values into the entity is required.
 	 */
 	protected boolean substituteValuesIfNecessary(
-			Object entity, 
-			Serializable id, 
-			Object[] values, 
+			Object entity,
+			Serializable id,
+			Object[] values,
 			EntityPersister persister,
-			SessionImplementor source
-	) {
+			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() ) {
@@ -386,7 +405,7 @@
 					values,
 					persister.getVersionProperty(),
 					persister.getVersionType(),
-			        source
+					source
 			) || substitute;
 		}
 		return substitute;
@@ -394,23 +413,23 @@
 
 	/**
 	 * 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
+	 * @param anything Generally cascade-specific data
 	 */
 	protected void cascadeBeforeSave(
 			EventSource source,
 			EntityPersister persister,
 			Object entity,
-			Object anything)
-	throws HibernateException {
+			Object anything) {
 
 		// 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);
+					.cascade( persister, entity, anything );
 		}
 		finally {
 			source.getPersistenceContext().decrementCascadeLevel();
@@ -419,97 +438,103 @@
 
 	/**
 	 * 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
+	 * @param anything Generally cascade-specific data
 	 */
 	protected void cascadeAfterSave(
 			EventSource source,
-	        EntityPersister persister,
-	        Object entity,
-			Object anything)
-	throws HibernateException {
+			EntityPersister persister,
+			Object entity,
+			Object anything) {
 
 		// 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);
+					.cascade( persister, entity, anything );
 		}
 		finally {
 			source.getPersistenceContext().decrementCascadeLevel();
 		}
 	}
-	
+
 	protected abstract CascadingAction getCascadeAction();
-	
+
 	/**
 	 * Determine whether the entity is persistent, detached, or transient
+	 *
+	 * @param entity The entity to check
+	 * @param entityName The name of the entity
+	 * @param entry The entity's entry in the persistence context
+	 * @param source The originating session.
+	 *
+	 * @return The state.
 	 */
 	protected int getEntityState(
-			Object entity, 
-			String entityName, 
+			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
-			
+			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) 
-						);
+					log.trace(
+							"persistent instance of: " +
+									getLoggableName( entityName, entity )
+					);
 				}
 				return PERSISTENT;
 			}
-			else { 
+			else {
 				//ie. e.status==DELETED
 				if ( log.isTraceEnabled() ) {
-					log.trace( 
-							"deleted instance of: " + 
-							getLoggableName(entityName, entity) 
-						);
+					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) 
-						);
+					log.trace(
+							"transient instance of: " +
+									getLoggableName( entityName, entity )
+					);
 				}
 				return TRANSIENT;
 			}
 			else {
 				if ( log.isTraceEnabled() ) {
-					log.trace( 
-							"detached instance of: " + 
-							getLoggableName(entityName, entity) 
-						);
+					log.trace(
+							"detached instance of: " +
+									getLoggableName( entityName, entity )
+					);
 				}
 				return DETACHED;
 			}
 
 		}
 	}
-	
+
 	protected String getLoggableName(String entityName, Object entity) {
-		return entityName==null ? entity.getClass().getName() : entityName;
+		return entityName == null ? entity.getClass().getName() : entityName;
 	}
-	
+
 	protected Boolean getAssumedUnsaved() {
 		return null;
 	}

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultDeleteEventListener.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -6,6 +6,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.hibernate.CacheMode;
 import org.hibernate.HibernateException;
 import org.hibernate.LockMode;
@@ -38,21 +39,31 @@
  */
 public class DefaultDeleteEventListener implements DeleteEventListener {
 
-	private static final Log log = LogFactory.getLog(DefaultDeleteEventListener.class);
+	private static final Log log = LogFactory.getLog( DefaultDeleteEventListener.class );
 
-    /** Handle the given delete event.
-     *
-     * @param event The delete event to be handled.
-     * @throws HibernateException
-     */
+	/**
+	 * Handle the given delete event.
+	 *
+	 * @param event The delete event to be handled.
+	 *
+	 * @throws HibernateException
+	 */
 	public void onDelete(DeleteEvent event) throws HibernateException {
 		onDelete( event, new IdentitySet() );
 	}
 
+	/**
+	 * 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() );
 
@@ -79,16 +90,16 @@
 
 			if ( id == null ) {
 				throw new TransientObjectException(
-					"the detached instance passed to delete() had a null identifier"
+						"the detached instance passed to delete() had a null identifier"
 				);
 			}
-			
+
 			EntityKey key = new EntityKey( id, persister, source.getEntityMode() );
 
-			persistenceContext.checkUniqueness(key, entity);
+			persistenceContext.checkUniqueness( key, entity );
 
-			new OnUpdateVisitor( source, id ).process( entity, persister );
-			
+			new OnUpdateVisitor( source, id, entity ).process( entity, persister );
+
 			version = persister.getVersion( entity, source.getEntityMode() );
 
 			entityEntry = persistenceContext.addEntity(
@@ -102,7 +113,7 @@
 					persister,
 					false,
 					false
-				);
+			);
 		}
 		else {
 			log.trace( "deleting a persistent instance" );
@@ -123,7 +134,9 @@
 				);
 		}*/
 
-		if ( invokeDeleteLifecycle( source, entity, persister ) ) return;
+		if ( invokeDeleteLifecycle( source, entity, persister ) ) {
+			return;
+		}
 
 		deleteEntity( source, entity, entityEntry, event.isCascadeDeleteEnabled(), persister, transientEntities );
 
@@ -132,6 +145,14 @@
 		}
 	}
 
+	/**
+	 * Called when we have recognized an attempt to delete a detached entity.
+	 * <p/>
+	 * This is perfectly valid in Hibernate usage; JPA, however, forbids this.
+	 * Thus, this is a hook for HEM to affect this behavior.
+	 *
+	 * @param event The event.
+	 */
 	protected void performDetachedEntityDeletionCheck(DeleteEvent event) {
 		// ok in normal Hibernate usage to delete a detached entity; JPA however
 		// forbids it, thus this is a hook for HEM to affect this behavior
@@ -168,19 +189,31 @@
 		cascadeAfterDelete( session, persister, entity, transientEntities );
 	}
 
+	/**
+	 * 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) throws HibernateException {
+			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() )
-				);
+							MessageHelper.infoString( persister, entityEntry.getId(), session.getFactory() )
+			);
 		}
 
 		final PersistenceContext persistenceContext = session.getPersistenceContext();
@@ -196,7 +229,7 @@
 		}
 
 		final Object[] deletedState = createDeletedState( persister, currentState, session );
-		entityEntry.setDeletedState(deletedState);
+		entityEntry.setDeletedState( deletedState );
 
 		session.getInterceptor().onDelete(
 				entity,
@@ -207,15 +240,15 @@
 		);
 
 		// 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()  );
+		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)
+		new ForeignKeys.Nullifier( entity, true, false, session )
 				.nullifyTransientReferences( entityEntry.getDeletedState(), propTypes );
-		new Nullability(session).checkNullability( entityEntry.getDeletedState(), persister, true );
-		persistenceContext.getNullifiableEntityKeys().add(key);
+		new Nullability( session ).checkNullability( entityEntry.getDeletedState(), persister, true );
+		persistenceContext.getNullifiableEntityKeys().add( key );
 
 		// Ensures that containing deletions happen before sub-deletions
 		session.getActionQueue().addAction(
@@ -251,23 +284,23 @@
 	protected boolean invokeDeleteLifecycle(EventSource session, Object entity, EntityPersister persister) {
 		if ( persister.implementsLifecycle( session.getEntityMode() ) ) {
 			log.debug( "calling onDelete()" );
-			if ( ( (Lifecycle) entity ).onDelete(session) ) {
-				log.debug("deletion vetoed by onDelete()");
+			if ( ( ( Lifecycle ) entity ).onDelete( session ) ) {
+				log.debug( "deletion vetoed by onDelete()" );
 				return true;
 			}
 		}
 		return false;
 	}
-	
+
 	protected void cascadeBeforeDelete(
 			EventSource session,
-	        EntityPersister persister,
-	        Object entity,
-	        EntityEntry entityEntry,
-	        Set transientEntities) throws HibernateException {
+			EntityPersister persister,
+			Object entity,
+			EntityEntry entityEntry,
+			Set transientEntities) throws HibernateException {
 
 		CacheMode cacheMode = session.getCacheMode();
-		session.setCacheMode(CacheMode.GET);
+		session.setCacheMode( CacheMode.GET );
 		session.getPersistenceContext().incrementCascadeLevel();
 		try {
 			// cascade-delete to collections BEFORE the collection owner is deleted
@@ -276,18 +309,18 @@
 		}
 		finally {
 			session.getPersistenceContext().decrementCascadeLevel();
-			session.setCacheMode(cacheMode);
+			session.setCacheMode( cacheMode );
 		}
 	}
 
 	protected void cascadeAfterDelete(
 			EventSource session,
-	        EntityPersister persister,
-	        Object entity,
-	        Set transientEntities) throws HibernateException {
+			EntityPersister persister,
+			Object entity,
+			Set transientEntities) throws HibernateException {
 
 		CacheMode cacheMode = session.getCacheMode();
-		session.setCacheMode(CacheMode.GET);
+		session.setCacheMode( CacheMode.GET );
 		session.getPersistenceContext().incrementCascadeLevel();
 		try {
 			// cascade-delete to many-to-one AFTER the parent was deleted
@@ -296,7 +329,7 @@
 		}
 		finally {
 			session.getPersistenceContext().decrementCascadeLevel();
-			session.setCacheMode(cacheMode);
+			session.setCacheMode( cacheMode );
 		}
 	}
 

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultReplicateEventListener.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -30,44 +30,43 @@
  */
 public class DefaultReplicateEventListener extends AbstractSaveEventListener implements ReplicateEventListener {
 
-	private static final Log log = LogFactory.getLog(DefaultReplicateEventListener.class);
+	private static final Log log = LogFactory.getLog( DefaultReplicateEventListener.class );
 
-	/** 
+	/**
 	 * Handle the given replicate event.
 	 *
 	 * @param event The replicate event to be handled.
-	 * @throws HibernateException
+	 *
+	 * @throws TransientObjectException An invalid attempt to replicate a transient entity.
 	 */
-	public void onReplicate(ReplicateEvent event) throws HibernateException {
-
+	public void onReplicate(ReplicateEvent event) {
 		final EventSource source = event.getSession();
-		
 		if ( source.getPersistenceContext().reassociateIfUninitializedProxy( event.getObject() ) ) {
-			log.trace("uninitialized proxy passed to replicate()");
+			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()");
+		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()");
+		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
@@ -75,14 +74,16 @@
 		}
 		else {
 			//what is the version on the database?
-			oldVersion = persister.getCurrentVersion(id, source);
+			oldVersion = persister.getCurrentVersion( id, source );
 		}
 
-		if ( oldVersion!=null ) {
+		if ( oldVersion != null ) {
 			//existing row - do an update if appropriate
 			if ( log.isTraceEnabled() ) {
-				log.trace( "found existing row for " + 
-					MessageHelper.infoString( persister, id, source.getFactory() ) );
+				log.trace(
+						"found existing row for " +
+								MessageHelper.infoString( persister, id, source.getFactory() )
+				);
 			}
 
 			boolean canReplicate = replicationMode.shouldOverwriteCurrentVersion(
@@ -92,26 +93,28 @@
 					persister.getVersionType()
 			);
 
-			if (canReplicate) {
+			if ( canReplicate ) {
 				//will result in a SQL UPDATE:
-				performReplication(entity, id, oldVersion, persister, replicationMode, source);
+				performReplication( entity, id, oldVersion, persister, replicationMode, source );
 			}
 			else {
 				//else do nothing (don't even reassociate object!)
-				log.trace("no need to replicate");
+				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() ) );
+				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 ? 
+			final EntityKey key = regenerate ?
 					null : new EntityKey( id, persister, source.getEntityMode() );
 
 			performSaveOrReplicate(
@@ -121,77 +124,74 @@
 					regenerate,
 					replicationMode,
 					source,
-			        true
+					true
 			);
 
 		}
 	}
 
-	protected boolean visitCollectionsBeforeSave(Serializable id, Object[] values, Type[] types, EventSource source) {
+	protected boolean visitCollectionsBeforeSave(Object entity, Serializable id, Object[] values, Type[] types, EventSource source) {
 		//TODO: we use two visitors here, inefficient!
-		OnReplicateVisitor visitor = new OnReplicateVisitor(source, id, false);
-		visitor.processEntityPropertyValues(values, types);
-		return super.visitCollectionsBeforeSave(id, values, types, source);
+		OnReplicateVisitor visitor = new OnReplicateVisitor( source, id, entity, false );
+		visitor.processEntityPropertyValues( values, types );
+		return super.visitCollectionsBeforeSave( entity, id, values, types, source );
 	}
 
 	protected boolean substituteValuesIfNecessary(
-			Object entity, 
-			Serializable id, 
-			Object[] values, 
+			Object entity,
+			Serializable id,
+			Object[] values,
 			EntityPersister persister,
-			SessionImplementor source
-	) {
+			SessionImplementor source) {
 		return false;
 	}
-	
+
 	protected boolean isVersionIncrementDisabled() {
 		return true;
 	}
-	
-	private final void performReplication(
+
+	private void performReplication(
 			Object entity,
 			Serializable id,
 			Object version,
 			EntityPersister persister,
 			ReplicationMode replicationMode,
-			EventSource source) 
-	throws HibernateException {
+			EventSource source) throws HibernateException {
 
 		if ( log.isTraceEnabled() ) {
-			log.trace( 
-				"replicating changes to " + 
-				MessageHelper.infoString( persister, id, source.getFactory() ) 
+			log.trace(
+					"replicating changes to " +
+							MessageHelper.infoString( persister, id, source.getFactory() )
 			);
 		}
 
-		new OnReplicateVisitor(source, id, true).process( entity, persister );
+		new OnReplicateVisitor( source, id, entity, true ).process( entity, persister );
 
-		source.getPersistenceContext().addEntity( 
-				entity, 
-				Status.MANAGED, 
-				null, 
-				new EntityKey( id, persister, source.getEntityMode() ), 
-				version, 
-				LockMode.NONE, 
-				true, 
-				persister, 
-				true, 
+		source.getPersistenceContext().addEntity(
+				entity,
+				Status.MANAGED,
+				null,
+				new EntityKey( id, persister, source.getEntityMode() ),
+				version,
+				LockMode.NONE,
+				true,
+				persister,
+				true,
 				false
-			);
+		);
 
 		cascadeAfterReplicate( entity, persister, replicationMode, source );
 	}
 
 	private void cascadeAfterReplicate(
-			Object entity, 
-			EntityPersister persister, 
-			ReplicationMode replicationMode, 
-			EventSource source
-	) {
+			Object entity,
+			EntityPersister persister,
+			ReplicationMode replicationMode,
+			EventSource source) {
 		source.getPersistenceContext().incrementCascadeLevel();
 		try {
-			new Cascade(CascadingAction.REPLICATE, Cascade.AFTER_UPDATE, source)
-					.cascade(persister, entity, replicationMode);
+			new Cascade( CascadingAction.REPLICATE, Cascade.AFTER_UPDATE, source )
+					.cascade( persister, entity, replicationMode );
 		}
 		finally {
 			source.getPersistenceContext().decrementCascadeLevel();

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -5,6 +5,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.hibernate.AssertionFailure;
 import org.hibernate.EntityMode;
 import org.hibernate.HibernateException;
@@ -27,218 +28,240 @@
 import org.hibernate.proxy.HibernateProxy;
 
 /**
- * Defines the default update event listener used by hibernate for updating
- * transient entities in response to generated update events.
+ * Defines the default listener used by Hibernate for handling save-update
+ * events.
  *
- * @author Steve Ebersole, Gavin King
+ * @author Steve Ebersole
+ * @author Gavin King
  */
 public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener implements SaveOrUpdateEventListener {
 
-	private static final Log log = LogFactory.getLog(DefaultSaveOrUpdateEventListener.class);
+	private static final Log log = LogFactory.getLog( DefaultSaveOrUpdateEventListener.class );
 
-	/** 
+	/**
 	 * Handle the given update event.
 	 *
 	 * @param event The update event to be handled.
-	 * @throws HibernateException
 	 */
-	public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException {
-		
+	public void onSaveOrUpdate(SaveOrUpdateEvent event) {
 		final SessionImplementor source = event.getSession();
 		final Object object = event.getObject();
+		final Serializable requestedId = event.getRequestedId();
 
-		final Serializable requestedId = event.getRequestedId();
-		if ( requestedId!=null ) {
+		if ( requestedId != null ) {
 			//assign the requested id to the proxy, *before* 
 			//reassociating the proxy
 			if ( object instanceof HibernateProxy ) {
-				( (HibernateProxy) object ).getHibernateLazyInitializer().setIdentifier(requestedId);
+				( ( HibernateProxy ) object ).getHibernateLazyInitializer().setIdentifier( requestedId );
 			}
 		}
-		
-		if ( reassociateIfUninitializedProxy(object, source) ) {
-			log.trace("reassociated uninitialized proxy");
+
+		if ( reassociateIfUninitializedProxy( object, source ) ) {
+			log.trace( "reassociated uninitialized proxy" );
 			// an uninitialized proxy, noop, don't even need to 
 			// return an id, since it is never a save()
 		}
 		else {
 			//initialize properties of the event:
-			final Object entity = source.getPersistenceContext().unproxyAndReassociate(object);
-			event.setEntity(entity);
-			event.setEntry( source.getPersistenceContext().getEntry(entity) );
+			final Object entity = source.getPersistenceContext().unproxyAndReassociate( object );
+			event.setEntity( entity );
+			event.setEntry( source.getPersistenceContext().getEntry( entity ) );
 			//return the id in the event object
-			event.setResultId( performSaveOrUpdate(event) );
+			event.setResultId( performSaveOrUpdate( event ) );
 		}
-		
+
 	}
-	
+
 	protected boolean reassociateIfUninitializedProxy(Object object, SessionImplementor source) {
-		return source.getPersistenceContext().reassociateIfUninitializedProxy(object);
+		return source.getPersistenceContext().reassociateIfUninitializedProxy( object );
 	}
-	
+
 	protected Serializable performSaveOrUpdate(SaveOrUpdateEvent event) {
-		
-		// use various roles to determine if the instance is 
-		// transient, persistent or detached:
-		
-		int entityState = getEntityState( 
-				event.getEntity(), 
-				event.getEntityName(), 
-				event.getEntry(), 
-				event.getSession() 
-			);
-		
-		switch (entityState) {
-			case DETACHED: 
-				entityIsDetached(event); 
+		int entityState = getEntityState(
+				event.getEntity(),
+				event.getEntityName(),
+				event.getEntry(),
+				event.getSession()
+		);
+
+		switch ( entityState ) {
+			case DETACHED:
+				entityIsDetached( event );
 				return null;
 			case PERSISTENT:
-				return entityIsPersistent(event);
+				return entityIsPersistent( event );
 			default: //TRANSIENT or DELETED
-				return entityIsTransient(event);	
+				return entityIsTransient( event );
 		}
-		
 	}
-	
+
 	protected Serializable entityIsPersistent(SaveOrUpdateEvent event) throws HibernateException {
-		
-		log.trace("ignoring persistent instance");
-		
+		log.trace( "ignoring persistent instance" );
+
 		EntityEntry entityEntry = event.getEntry();
-		if ( entityEntry==null ) {
-			throw new AssertionFailure("entity was transient or detached");
+		if ( entityEntry == null ) {
+			throw new AssertionFailure( "entity was transient or detached" );
 		}
 		else {
-			
+
 			if ( entityEntry.getStatus() == Status.DELETED ) {
-				throw new AssertionFailure("entity was deleted");
+				throw new AssertionFailure( "entity was deleted" );
 			}
-			
+
 			final SessionFactoryImplementor factory = event.getSession().getFactory();
 
 			Serializable requestedId = event.getRequestedId();
-			
+
 			Serializable savedId;
 			if ( requestedId == null ) {
 				savedId = entityEntry.getId();
 			}
 			else {
-				
+
 				final boolean isEqual = !entityEntry.getPersister().getIdentifierType()
 						.isEqual( requestedId, entityEntry.getId(), event.getSession().getEntityMode(), factory );
-				
+
 				if ( isEqual ) {
 					throw new PersistentObjectException(
 							"object passed to save() was already persistent: " +
-							MessageHelper.infoString( entityEntry.getPersister(), requestedId, factory )
-						);
+									MessageHelper.infoString( entityEntry.getPersister(), requestedId, factory )
+					);
 				}
-				
+
 				savedId = requestedId;
-				
+
 			}
-			
+
 			if ( log.isTraceEnabled() ) {
-				log.trace( 
-						"object already associated with session: " + 
-						MessageHelper.infoString( entityEntry.getPersister(), savedId, factory )
-					);
+				log.trace(
+						"object already associated with session: " +
+								MessageHelper.infoString( entityEntry.getPersister(), savedId, factory )
+				);
 			}
-			
+
 			return savedId;
-			
+
 		}
 	}
-		
-	/** 
-	 * Handle the given save event.
+
+	/**
+	 * The given save-update event named a transient entity.
+	 * <p/>
+	 * Here, we will perform the save processing.
 	 *
 	 * @param event The save event to be handled.
-	 * @throws HibernateException
+	 *
+	 * @return The entity's identifier after saving.
 	 */
-	protected Serializable entityIsTransient(SaveOrUpdateEvent event) throws HibernateException {
-		
-		log.trace("saving transient instance");
+	protected Serializable entityIsTransient(SaveOrUpdateEvent event) {
 
-		final EventSource source = event.getSession();		
+		log.trace( "saving transient instance" );
 
+		final EventSource source = event.getSession();
+
 		EntityEntry entityEntry = event.getEntry();
 		if ( entityEntry != null ) {
 			if ( entityEntry.getStatus() == Status.DELETED ) {
-				source.forceFlush(entityEntry);
+				source.forceFlush( entityEntry );
 			}
 			else {
-				throw new AssertionFailure("entity was persistent");
+				throw new AssertionFailure( "entity was persistent" );
 			}
 		}
-		
-		Serializable id = saveWithGeneratedOrRequestedId(event);
 
+		Serializable id = saveWithGeneratedOrRequestedId( event );
+
 		source.getPersistenceContext().reassociateProxy( event.getObject(), id );
-		
+
 		return id;
 	}
-	
+
 	/**
 	 * Save the transient instance, assigning the right identifier
+	 *
+	 * @param event The initiating event.
+	 *
+	 * @return The entity's identifier value after saving.
 	 */
 	protected Serializable saveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) {
 		return saveWithGeneratedId(
-				event.getEntity(), 
-				event.getEntityName(), 
-				null, 
+				event.getEntity(),
+				event.getEntityName(),
+				null,
 				event.getSession(),
-		        true
+				true
 		);
 	}
-	
-	/** 
-	 * Handle the given update event.
+
+	/**
+	 * The given save-update event named a detached entity.
+	 * <p/>
+	 * Here, we will perform the update processing.
 	 *
 	 * @param event The update event to be handled.
-	 * @throws HibernateException
 	 */
-	protected void entityIsDetached(SaveOrUpdateEvent event) throws HibernateException {
-		
-		log.trace("updating detached instance");
-				
-		
-		if ( event.getSession().getPersistenceContext().isEntryFor( event.getEntity() ) ) { 
+	protected void entityIsDetached(SaveOrUpdateEvent event) {
+
+		log.trace( "updating detached instance" );
+
+
+		if ( event.getSession().getPersistenceContext().isEntryFor( event.getEntity() ) ) {
 			//TODO: assertion only, could be optimized away
-			throw new AssertionFailure("entity was persistent");
+			throw new AssertionFailure( "entity was persistent" );
 		}
-		
+
 		Object entity = event.getEntity();
 
 		EntityPersister persister = event.getSession().getEntityPersister( event.getEntityName(), entity );
 
-		event.setRequestedId( getUpdateId( entity, persister, event.getRequestedId(), event.getSession().getEntityMode() ) );
-		
-		performUpdate(event, entity, persister);
+		event.setRequestedId(
+				getUpdateId(
+						entity, persister, event.getRequestedId(), event.getSession().getEntityMode()
+				)
+		);
 
+		performUpdate( event, entity, persister );
+
 	}
-	
-	protected Serializable getUpdateId(Object entity, EntityPersister persister, Serializable requestedId, EntityMode entityMode)
-	throws HibernateException {
+
+	/**
+	 * Determine the id to use for updating.
+	 *
+	 * @param entity The entity.
+	 * @param persister The entity persister
+	 * @param requestedId The requested identifier
+	 * @param entityMode The entity mode.
+	 *
+	 * @return The id.
+	 *
+	 * @throws TransientObjectException If the entity is considered transient.
+	 */
+	protected Serializable getUpdateId(
+			Object entity,
+			EntityPersister persister,
+			Serializable requestedId,
+			EntityMode entityMode) {
 		// use the id assigned to the instance
-		Serializable id = persister.getIdentifier(entity, entityMode);
-		if ( id==null ) {
+		Serializable id = persister.getIdentifier( entity, entityMode );
+		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()
-				);
+							persister.getEntityName()
+			);
 		}
 		else {
 			return id;
 		}
-			
+
 	}
 
-	protected void performUpdate(SaveOrUpdateEvent event, Object entity, EntityPersister persister) 
-	throws HibernateException {
-	
+	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 );
@@ -246,27 +269,29 @@
 		else {
 
 			if ( log.isTraceEnabled() ) {
-				log.trace( 
-						"updating " + 
-						MessageHelper.infoString( persister, event.getRequestedId(), event.getSession().getFactory() ) 
-					);
+				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() ).process( entity, persister );
-			
+
+			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;
@@ -288,28 +313,28 @@
 					LockMode.NONE,
 					true,
 					persister,
-					false, 
+					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() )
 				);
-			
-			persister.afterReassociate(entity, source);
-	
-			if ( log.isTraceEnabled() ) {
-				log.trace( 
-						"updating " + 
-						MessageHelper.infoString( persister, event.getRequestedId(), source.getFactory() ) 
-					);
 			}
-	
-			cascadeOnUpdate(event, persister, entity);
-			
+
+			cascadeOnUpdate( event, persister, entity );
+
 		}
 	}
 
 	protected boolean invokeUpdateLifecycle(Object entity, EntityPersister persister, EventSource source) {
 		if ( persister.implementsLifecycle( source.getEntityMode() ) ) {
 			log.debug( "calling onUpdate()" );
-			if ( ( ( Lifecycle ) entity ).onUpdate(source) ) {
+			if ( ( ( Lifecycle ) entity ).onUpdate( source ) ) {
 				log.debug( "update vetoed by onUpdate()" );
 				return true;
 			}
@@ -329,8 +354,8 @@
 		EventSource source = event.getSession();
 		source.getPersistenceContext().incrementCascadeLevel();
 		try {
-			new Cascade(CascadingAction.SAVE_UPDATE, Cascade.AFTER_UPDATE, source)
-					.cascade(persister, entity);
+			new Cascade( CascadingAction.SAVE_UPDATE, Cascade.AFTER_UPDATE, source )
+					.cascade( persister, entity );
 		}
 		finally {
 			source.getPersistenceContext().decrementCascadeLevel();

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnLockVisitor.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -14,60 +14,55 @@
  * When a transient entity is passed to lock(), we must inspect all its collections and
  * 1. associate any uninitialized PersistentCollections with this session
  * 2. associate any initialized PersistentCollections with this session, using the
- *    existing snapshot
+ * existing snapshot
  * 3. throw an exception for each "new" collection
  *
  * @author Gavin King
  */
 public class OnLockVisitor extends ReattachVisitor {
 
-	public OnLockVisitor(EventSource session, Serializable key) {
-		super(session, key);
+	public OnLockVisitor(EventSource session, Serializable key, Object owner) {
+		super( session, key, owner );
 	}
 
-	Object processCollection(Object collection, CollectionType type)
-		throws HibernateException {
+	Object processCollection(Object collection, CollectionType type) throws HibernateException {
 
 		SessionImplementor session = getSession();
 		CollectionPersister persister = session.getFactory().getCollectionPersister( type.getRole() );
 
-		if (collection==null) {
+		if ( collection == null ) {
 			//do nothing
 		}
 		else if ( collection instanceof PersistentCollection ) {
-			PersistentCollection persistentCollection = (PersistentCollection) collection;
-
-			if ( persistentCollection.setCurrentSession(session) ) {
-
-				if ( isOwnerUnchanged( persistentCollection, persister, getKey() ) ) {
+			PersistentCollection persistentCollection = ( PersistentCollection ) collection;
+			if ( persistentCollection.setCurrentSession( session ) ) {
+				if ( isOwnerUnchanged( persistentCollection, persister, extractCollectionKeyFromOwner( persister ) ) ) {
 					// a "detached" collection that originally belonged to the same entity
 					if ( persistentCollection.isDirty() ) {
-						throw new HibernateException("reassociated object has dirty collection");
+						throw new HibernateException( "reassociated object has dirty collection" );
 					}
-					reattachCollection(persistentCollection, type);
+					reattachCollection( persistentCollection, type );
 				}
 				else {
 					// a "detached" collection that belonged to a different entity
-					throw new HibernateException("reassociated object has dirty collection reference");
+					throw new HibernateException( "reassociated object has dirty collection reference" );
 				}
-
 			}
 			else {
 				// a collection loaded in the current session
 				// can not possibly be the collection belonging
 				// to the entity passed to update()
-				throw new HibernateException("reassociated object has dirty collection reference");
+				throw new HibernateException( "reassociated object has dirty collection reference" );
 			}
-
 		}
 		else {
 			// brand new collection
 			//TODO: or an array!! we can't lock objects with arrays now??
-			throw new HibernateException("reassociated object has dirty collection reference (or an array)");
+			throw new HibernateException( "reassociated object has dirty collection reference (or an array)" );
 		}
 
 		return null;
 
 	}
-	
+
 }

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnReplicateVisitor.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -10,40 +10,43 @@
 import org.hibernate.type.CollectionType;
 
 /**
- * When an entity is passed to replicate(), and there is an existing row, we must 
+ * When an entity is passed to replicate(), and there is an existing row, we must
  * inspect all its collections and
  * 1. associate any uninitialized PersistentCollections with this session
  * 2. associate any initialized PersistentCollections with this session, using the
- *    existing snapshot
+ * existing snapshot
  * 3. execute a collection removal (SQL DELETE) for each null collection property
- *    or "new" collection
+ * or "new" collection
  *
  * @author Gavin King
  */
 public class OnReplicateVisitor extends ReattachVisitor {
-	
+
 	private boolean isUpdate;
-	
-	OnReplicateVisitor(EventSource session, Serializable key, boolean isUpdate) {
-		super(session, key);
+
+	OnReplicateVisitor(EventSource session, Serializable key, Object owner, boolean isUpdate) {
+		super( session, key, owner );
 		this.isUpdate = isUpdate;
 	}
 
 	Object processCollection(Object collection, CollectionType type)
-		throws HibernateException {
-		
-		if (collection==CollectionType.UNFETCHED_COLLECTION) return null;
+			throws HibernateException {
 
+		if ( collection == CollectionType.UNFETCHED_COLLECTION ) {
+			return null;
+		}
+
 		EventSource session = getSession();
-		Serializable key = getKey();
 		CollectionPersister persister = session.getFactory().getCollectionPersister( type.getRole() );
 
-		if (isUpdate) removeCollection(persister, key, session);
-		if ( collection!=null && (collection instanceof PersistentCollection) ) {
-			PersistentCollection wrapper = (PersistentCollection) collection;
-			wrapper.setCurrentSession(session);
+		if ( isUpdate ) {
+			removeCollection( persister, extractCollectionKeyFromOwner( persister ), session );
+		}
+		if ( collection != null && ( collection instanceof PersistentCollection ) ) {
+			PersistentCollection wrapper = ( PersistentCollection ) collection;
+			wrapper.setCurrentSession( session );
 			if ( wrapper.wasInitialized() ) {
-				session.getPersistenceContext().addNewCollection(persister, wrapper);
+				session.getPersistenceContext().addNewCollection( persister, wrapper );
 			}
 			else {
 				reattachCollection( wrapper, type );

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/OnUpdateVisitor.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -21,51 +21,49 @@
  */
 public class OnUpdateVisitor extends ReattachVisitor {
 
-	OnUpdateVisitor(EventSource session, Serializable key) {
-		super(session, key);
+	OnUpdateVisitor(EventSource session, Serializable key, Object owner) {
+		super( session, key, owner );
 	}
 
-	Object processCollection(Object collection, CollectionType type)
-		throws HibernateException {
+	/**
+	 * {@inheritDoc}
+	 */
+	Object processCollection(Object collection, CollectionType type) throws HibernateException {
 		
-		if (collection==CollectionType.UNFETCHED_COLLECTION) return null;
+		if ( collection == CollectionType.UNFETCHED_COLLECTION ) {
+			return null;
+		}
 
 		EventSource session = getSession();
-		Serializable key = getKey();
 		CollectionPersister persister = session.getFactory().getCollectionPersister( type.getRole() );
 
+		final Serializable collectionKey = extractCollectionKeyFromOwner( persister );
 		if ( collection!=null && (collection instanceof PersistentCollection) ) {
 			PersistentCollection wrapper = (PersistentCollection) collection;
-
 			if ( wrapper.setCurrentSession(session) ) {
 				//a "detached" collection!
-
-				if ( !isOwnerUnchanged(wrapper, persister, key) ) {
+				if ( !isOwnerUnchanged( wrapper, persister, collectionKey ) ) {
 					// if the collection belonged to a different entity,
 					// clean up the existing state of the collection
-					removeCollection(persister, key, session);
+					removeCollection( persister, collectionKey, session );
 				}
-
 				reattachCollection(wrapper, type);
 			}
 			else {
 				// a collection loaded in the current session
 				// can not possibly be the collection belonging
 				// to the entity passed to update()
-				removeCollection(persister, key, session);
+				removeCollection(persister, collectionKey, session);
 			}
-
 		}
 		else {
 			// null or brand new collection
 			// this will also (inefficiently) handle arrays, which have
 			// no snapshot, so we can't do any better
-			removeCollection(persister, key, session);
-			//processArrayOrNewCollection(collection, type);
+			removeCollection(persister, collectionKey, session);
 		}
 
 		return null;
-
 	}
 
 }

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/ReattachVisitor.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -14,34 +14,51 @@
 import org.hibernate.type.Type;
 
 /**
- * Abstract superclass of visitors that reattach collections
+ * Abstract superclass of visitors that reattach collections.
+ *
  * @author Gavin King
  */
 public abstract class ReattachVisitor extends ProxyVisitor {
 	
-	private static final Log log = LogFactory.getLog(ReattachVisitor.class);
+	private static final Log log = LogFactory.getLog( ReattachVisitor.class );
 
-	private final Serializable key;
+	private final Serializable ownerIdentifier;
+	private final Object owner;
 
-	final Serializable getKey() {
-		return key;
+	public ReattachVisitor(EventSource session, Serializable ownerIdentifier, Object owner) {
+		super( session );
+		this.ownerIdentifier = ownerIdentifier;
+		this.owner = owner;
 	}
 
-	public ReattachVisitor(EventSource session, Serializable key) {
-		super(session);
-		this.key=key;
+	/**
+	 * Retrieve the identifier of the entity being visited.
+	 *
+	 * @return The entity's identifier.
+	 */
+	final Serializable getOwnerIdentifier() {
+		return ownerIdentifier;
 	}
 
-	Object processComponent(Object component, AbstractComponentType componentType)
-	throws HibernateException {
+	/**
+	 * Retrieve the entity being visited.
+	 *
+	 * @return The entity.
+	 */
+	final Object getOwner() {
+		return owner;
+	}
 
+	/**
+	 * {@inheritDoc}
+	 */
+	Object processComponent(Object component, AbstractComponentType componentType) throws HibernateException {
 		Type[] types = componentType.getSubtypes();
-		if (component==null) {
+		if ( component == null ) {
 			processValues( new Object[types.length], types );
 		}
 		else {
-			super.processComponent(component, componentType);
-			//processValues( componentType.getPropertyValues( component, getSession() ), types );
+			super.processComponent( component, componentType );
 		}
 
 		return null;
@@ -51,23 +68,35 @@
 	 * Schedules a collection for deletion.
 	 *
 	 * @param role The persister representing the collection to be removed.
-	 * @param id The id of the entity containing the collection to be removed.
+	 * @param collectionKey The collection key (differs from owner-id in the case of property-refs).
+	 * @param source The session from which the request originated.
 	 * @throws HibernateException
 	 */
-	public void removeCollection(CollectionPersister role, Serializable id, EventSource source) 
-	throws HibernateException {
-		if ( log.isTraceEnabled() )
+	void removeCollection(CollectionPersister role, Serializable collectionKey, EventSource source) throws HibernateException {
+		if ( log.isTraceEnabled() ) {
 			log.trace(
 					"collection dereferenced while transient " +
-					MessageHelper.collectionInfoString( role, id, source.getFactory() )
+					MessageHelper.collectionInfoString( role, ownerIdentifier, source.getFactory() )
 			);
-		/*if ( role.hasOrphanDelete() ) {
-			throw new HibernateException(
-				"You may not dereference a collection with cascade=\"all-delete-orphan\": " +
-				MessageHelper.infoString(role, id)
-			);
-		}*/
-		source.getActionQueue().addAction( new CollectionRemoveAction( null, role, id, false, source ) );
+		}
+		source.getActionQueue().addAction( new CollectionRemoveAction( null, role, collectionKey, false, source ) );
 	}
 
+	/**
+	 * This version is slightly different in that here we need to assume that
+	 * the owner is not yet associated with the session, and thus we cannot
+	 * rely on the owner's EntityEntry snapshot...
+	 * 
+	 * @param role The persister for the collection role being processed.
+	 * @return
+	 */
+	final Serializable extractCollectionKeyFromOwner(CollectionPersister role) {
+		if ( role.getCollectionType().useLHSPrimaryKey() ) {
+			return ownerIdentifier;
+		}
+		else {
+			return ( Serializable ) role.getOwnerEntityPersister().getPropertyValue( owner, role.getCollectionType().getLHSPropertyName(), getSession().getEntityMode() );
+		}
+
+	}
 }

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.hbm.xml	2006-12-07 21:53:41 UTC (rev 10949)
@@ -31,6 +31,10 @@
             <key column="userId" property-ref="userId"/>
             <one-to-many class="Account"/>
         </set>
+        <bag name="systems" table="USER_SYSTEM" lazy="true" inverse="false" cascade="all">
+            <key column="USER_ID" property-ref="userId" />
+            <element type="string" column="SYSTEM" />
+        </bag>
     </class>
 
     <class name="Address" table="PROPREF_ADDR">

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/Person.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -3,6 +3,8 @@
 
 import java.util.HashSet;
 import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
 
 /**
  * @author gavin
@@ -13,6 +15,8 @@
 	private Address address;
 	private String userId;
 	private Set accounts = new HashSet();
+	private List systems = new ArrayList();
+
 	/**
 	 * @return Returns the userId.
 	 */
@@ -73,4 +77,12 @@
 	public void setAccounts(Set accounts) {
 		this.accounts = accounts;
 	}
+
+	public List getSystems() {
+		return systems;
+	}
+
+	public void setSystems(List systems) {
+		this.systems = systems;
+	}
 }

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java	2006-12-07 21:53:10 UTC (rev 10948)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/propertyref/basic/PropertyRefTest.java	2006-12-07 21:53:41 UTC (rev 10949)
@@ -22,7 +22,7 @@
  * @author Gavin King
  */
 public class PropertyRefTest extends TestCase {
-	
+
 	public PropertyRefTest(String str) {
 		super(str);
 	}
@@ -39,7 +39,44 @@
 		cfg.setProperty(Environment.DEFAULT_BATCH_FETCH_SIZE, "1");
 		cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
 	}
-	
+
+	public String getCacheConcurrencyStrategy() {
+		return null;
+	}
+
+	public void testNonLazyBagKeyPropertyRef() {
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		Person p = new Person();
+		p.setName( "Steve" );
+		p.setUserId( "steve" );
+		p.getSystems().add( "QA" );
+		p.getSystems().add( "R&D" );
+		s.persist( p );
+		t.commit();
+		s.close();
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.createQuery( "from Person" ).list();
+		s.clear();
+		s.createSQLQuery( "select {p.*} from PROPREF_PERS {p}" )
+				.addEntity( "p", Person.class.getName() )
+				.list();
+		t.commit();
+		s.close();
+
+		s = openSession();
+		t = s.beginTransaction();
+		List results = s.createQuery( "from Person" ).list();
+		Iterator itr = results.iterator();
+		while ( itr.hasNext() ) {
+			s.delete( itr.next() );
+		}
+		t.commit();
+		s.close();
+	}
+
 	public void testManyToManyPropertyRef() {
 		// prepare some test data relating to the Group->Person many-to-many association
 		Session s = openSession();
@@ -78,7 +115,7 @@
 		t.commit();
 		s.close();
 	}
-	
+
 	public void testOneToOnePropertyRef() {
 		Session s = openSession();
 		Transaction t = s.beginTransaction();
@@ -102,7 +139,7 @@
 		s.save(act);
 		s.flush();
 		s.clear();
-		
+
 		p = (Person) s.get( Person.class, p.getId() ); //get address reference by outer join
 		p2 = (Person) s.get( Person.class, p2.getId() ); //get null address reference by outer join
 		assertNull( p2.getAddress() );
@@ -111,13 +148,13 @@
 		assertEquals( l.size(), 2 );
 		assertTrue( l.contains(p) && l.contains(p2) );
 		s.clear();
-		
+
 		l = s.createQuery("from Person p order by p.name").list(); //get address references by sequential selects
 		assertEquals( l.size(), 2 );
 		assertNull( ( (Person) l.get(0) ).getAddress() );
 		assertNotNull( ( (Person) l.get(1) ).getAddress() );
 		s.clear();
-		
+
 		l = s.createQuery("from Person p left join fetch p.address a order by a.country").list(); //get em by outer join
 		assertEquals( l.size(), 2 );
 		if ( ( (Person) l.get(0) ).getName().equals("Max") ) {
@@ -129,7 +166,7 @@
 			assertNotNull( ( (Person) l.get(0) ).getAddress() );
 		}
 		s.clear();
-		
+
 		l = s.createQuery("from Person p left join p.accounts a").list();
 		for ( int i=0; i<2; i++ ) {
 			Object[] row = (Object[]) l.get(i);
@@ -152,16 +189,16 @@
 		assertTrue( Hibernate.isInitialized(acc.getUser()) );
 		assertNotNull(acc.getUser());
 		assertTrue( acc.getUser().getAccounts().contains(acc) );
-		
+
 		s.createQuery("delete from Address").executeUpdate();
 		s.createQuery("delete from Account").executeUpdate(); // to not break constraint violation between Person and Account
 		s.createQuery("delete from Person").executeUpdate();
-		
+
 		t.commit();
 		s.close();
 	}
 
-	
+
 	public void testJoinFetchPropertyRef() {
 		Session s = openSession();
 		Transaction t = s.beginTransaction();
@@ -181,7 +218,7 @@
 		getSessions().getStatistics().clear();
 
 		p = (Person) s.get( Person.class, p.getId() ); //get address reference by outer join
-		
+
 		assertTrue( Hibernate.isInitialized( p.getAddress() ) );
 		assertNotNull( p.getAddress() );
         assertEquals( getSessions().getStatistics().getPrepareStatementCount(), 1 );
@@ -194,7 +231,7 @@
 		p = (Person) s.createCriteria(Person.class)
 			.setFetchMode("address", FetchMode.SELECT)
 			.uniqueResult(); //get address reference by select
-		
+
 		assertTrue( Hibernate.isInitialized( p.getAddress() ) );
 		assertNotNull( p.getAddress() );
         assertEquals( getSessions().getStatistics().getPrepareStatementCount(), 2 );
@@ -202,30 +239,30 @@
 
 		s.createQuery("delete from Address").executeUpdate();
 		s.createQuery("delete from Person").executeUpdate();
-		
+
 		t.commit();
 		s.close();
 	}
 
 	public void testForeignKeyCreation() {
 		PersistentClass classMapping = getCfg().getClassMapping("org.hibernate.test.propertyref.basic.Account");
-		
+
 		Iterator foreignKeyIterator = classMapping.getTable().getForeignKeyIterator();
 		boolean found = false;
 		while ( foreignKeyIterator.hasNext() ) {
 			ForeignKey element = (ForeignKey) foreignKeyIterator.next();
 			if(element.getReferencedEntityName().equals(Person.class.getName() ) ) {
-				
+
 				if(!element.isReferenceToPrimaryKey() ) {
 					List referencedColumns = element.getReferencedColumns();
 					Column column = (Column) referencedColumns.get(0);
 					if(column.getName().equals("person_userid") ) {
 						found = true; // extend test to include the columns
-					}				
+					}
 				}
 			}
 		}
-		
+
 		assertTrue("Property ref foreign key not found",found);
 	}
 }




More information about the hibernate-commits mailing list