[hibernate-commits] Hibernate SVN: r10783 - in branches/Branch_3_2/Hibernate3: src/org/hibernate/event/def src/org/hibernate/type test/org/hibernate/test/interceptor

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Sat Nov 11 00:12:40 EST 2006


Author: steve.ebersole at jboss.com
Date: 2006-11-11 00:12:37 -0500 (Sat, 11 Nov 2006)
New Revision: 10783

Added:
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/Image.hbm.xml
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/Image.java
Modified:
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultFlushEntityEventListener.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java
   branches/Branch_3_2/Hibernate3/src/org/hibernate/type/TypeFactory.java
   branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/InterceptorTest.java
Log:
HHH-1921 & HHH-2027: interceptor/listener changing  properties

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultFlushEntityEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultFlushEntityEventListener.java	2006-11-11 04:27:51 UTC (rev 10782)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultFlushEntityEventListener.java	2006-11-11 05:12:37 UTC (rev 10783)
@@ -232,16 +232,16 @@
 					);
 			}
 		}
+
+		boolean intercepted;
 		
-		boolean substitute;
-		
 		if ( !entry.isBeingReplicated() ) {
 			// give the Interceptor a chance to process property values, if the properties 
 			// were modified by the Interceptor, we need to set them back to the object
-			substitute = handleInterception(event);
+			intercepted = handleInterception( event );
 		}
 		else {
-			substitute = false;
+			intercepted = false;
 		}
 
 		validate( entity, persister, status, entityMode );
@@ -251,9 +251,9 @@
 
 		// if it was dirtied by a collection only
 		int[] dirtyProperties = event.getDirtyProperties();
-		if ( event.isDirtyCheckPossible() && dirtyProperties==null ) {
-			if ( !event.hasDirtyCollection() ) {
-				throw new AssertionFailure("dirty, but no dirty properties");
+		if ( event.isDirtyCheckPossible() && dirtyProperties == null ) {
+			if ( ! intercepted && !event.hasDirtyCollection() ) {
+				throw new AssertionFailure( "dirty, but no dirty properties" );
 			}
 			dirtyProperties = ArrayHelper.EMPTY_INT_ARRAY;
 		}
@@ -280,7 +280,7 @@
 					)
 			);
 		
-		return substitute;
+		return intercepted;
 	}
 
 	protected void validate(Object entity, EntityPersister persister, Status status, EntityMode entityMode) {
@@ -320,17 +320,15 @@
 			Object entity, 
 			EntityEntry entry, 
 			final Object[] values,
-			EntityPersister persister
-	) {
-		final boolean intercepted = session.getInterceptor().onFlushDirty(
+			EntityPersister persister) {
+		return session.getInterceptor().onFlushDirty(
 				entity,
 				entry.getId(),
 				values,
 				entry.getLoadedState(),
 				persister.getPropertyNames(),
 				persister.getPropertyTypes()
-			);
-		return intercepted;
+		);
 	}
 
 	/**

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java	2006-11-11 04:27:51 UTC (rev 10782)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/event/def/DefaultMergeEventListener.java	2006-11-11 05:12:37 UTC (rev 10783)
@@ -172,7 +172,7 @@
 		final Object copy = persister.instantiate( id, source.getEntityMode() );  //TODO: should this be Session.instantiate(Persister, ...)?
 		copyCache.put(entity, copy); //before cascade!
 		
-		// cascade first, so that all unsaved objects get their 
+		// cascade first, so that all unsaved objects get their
 		// copy created before we actually copy
 		//cascadeOnMerge(event, persister, entity, copyCache, Cascades.CASCADE_BEFORE_MERGE);
 		super.cascadeBeforeSave(source, persister, entity, copyCache);
@@ -350,27 +350,44 @@
 	}
 
 	protected void copyValues(
-			final EntityPersister persister, 
+			final EntityPersister persister,
 			final Object entity, 
 			final Object target, 
 			final SessionImplementor source,
 			final Map copyCache,
-			final ForeignKeyDirection foreignKeyDirection
-		) {
-			
-			final Object[] copiedValues = TypeFactory.replace(
+			final ForeignKeyDirection foreignKeyDirection) {
+
+		final Object[] copiedValues;
+
+		if ( foreignKeyDirection == ForeignKeyDirection.FOREIGN_KEY_TO_PARENT ) {
+			// this is the second pass through on a merge op, so here we limit the
+			// replacement to associations types (value types were already replaced
+			// during the first pass)
+			copiedValues = TypeFactory.replaceAssociations(
 					persister.getPropertyValues( entity, source.getEntityMode() ),
 					persister.getPropertyValues( target, source.getEntityMode() ),
 					persister.getPropertyTypes(),
 					source,
-					target, 
+					target,
 					copyCache,
 					foreignKeyDirection
-				);
-
-			persister.setPropertyValues( target, copiedValues, source.getEntityMode() );
+			);
 		}
+		else {
+			copiedValues = TypeFactory.replace(
+					persister.getPropertyValues( entity, source.getEntityMode() ),
+					persister.getPropertyValues( target, source.getEntityMode() ),
+					persister.getPropertyTypes(),
+					source,
+					target,
+					copyCache,
+					foreignKeyDirection
+			);
+		}
 
+		persister.setPropertyValues( target, copiedValues, source.getEntityMode() );
+	}
+
 	/** 
 	 * Perform any cascades needed as part of this copy event.
 	 *

Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/type/TypeFactory.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/type/TypeFactory.java	2006-11-11 04:27:51 UTC (rev 10782)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/type/TypeFactory.java	2006-11-11 05:12:37 UTC (rev 10783)
@@ -498,6 +498,40 @@
 		return copied;
 	}
 
+	/**
+	 * Apply the {@link Type#replace} operation across a series of values, as
+	 * long as the corresponding {@link Type} is an association.
+	 *
+	 * @param original The source of the state
+	 * @param target The target into which to replace the source values.
+	 * @param types The value types
+	 * @param session The orginating session
+	 * @param owner The entity "owning" the values
+	 * @param copyCache A map representing a cache of already replaced state
+	 * @param foreignKeyDirection FK directionality to be applied to the replacement
+	 * @return The replaced state
+	 */
+	public static Object[] replaceAssociations(
+			final Object[] original,
+			final Object[] target,
+			final Type[] types,
+			final SessionImplementor session,
+			final Object owner,
+			final Map copyCache,
+			final ForeignKeyDirection foreignKeyDirection) {
+		Object[] copied = new Object[original.length];
+		for ( int i = 0; i < types.length; i++ ) {
+			if ( original[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY
+					|| original[i] == BackrefPropertyAccessor.UNKNOWN 
+					|| !types[i].isAssociationType() ) {
+				copied[i] = target[i];
+			}
+			else {
+				copied[i] = types[i].replace( original[i], target[i], session, owner, copyCache, foreignKeyDirection );
+			}
+		}
+		return copied;
+	}
 
 
 	/**

Added: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/Image.hbm.xml
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/Image.hbm.xml	2006-11-11 04:27:51 UTC (rev 10782)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/Image.hbm.xml	2006-11-11 05:12:37 UTC (rev 10783)
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
+
+<hibernate-mapping package="org.hibernate.test.interceptor">
+
+    <class name="Image" table="image" abstract="false" select-before-update="true" >
+        <id name="id" type="java.lang.Long" column="id">
+            <generator class="native"/>
+        </id>
+        <component name="details" class="Image$Details">
+            <property name="perm1" not-null="true" type="long" column="permissions"/>
+            <property name="comment" type="string" column="comment_txt"/>
+        </component>
+        <property name="name" type="java.lang.String" column="name" not-null="true"/>
+    </class>
+
+</hibernate-mapping>

Added: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/Image.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/Image.java	2006-11-11 04:27:51 UTC (rev 10782)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/Image.java	2006-11-11 05:12:37 UTC (rev 10783)
@@ -0,0 +1,63 @@
+package org.hibernate.test.interceptor;
+
+public class Image {
+
+	private Long id;
+	private String name;
+	private Details details;
+
+	public Details getDetails() {
+		return details;
+	}
+
+	public Long getId() {
+		return id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setDetails(Details details) {
+		this.details = details;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String toString() {
+		return "Image/" + ( details == null ? "no details" : details.toString() );
+	}
+
+	public static class Details {
+		private long perm1 = -1; // all bits turned on.
+		private String comment;
+
+		protected long getPerm1() {
+			return this.perm1;
+		}
+
+		protected void setPerm1(long value) {
+			this.perm1 = value;
+		}
+
+		public String getComment() {
+			return comment;
+		}
+
+		public void setComment(String comment) {
+			this.comment = comment;
+		}
+
+		public String toString() {
+			return "Details=" + perm1;
+		}
+	}
+
+}
+

Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/InterceptorTest.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/InterceptorTest.java	2006-11-11 04:27:51 UTC (rev 10782)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/interceptor/InterceptorTest.java	2006-11-11 05:12:37 UTC (rev 10783)
@@ -2,12 +2,15 @@
 package org.hibernate.test.interceptor;
 
 import java.util.List;
+import java.io.Serializable;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
 
 import org.hibernate.Session;
 import org.hibernate.Transaction;
+import org.hibernate.EmptyInterceptor;
+import org.hibernate.type.Type;
 import org.hibernate.test.TestCase;
 
 /**
@@ -54,8 +57,83 @@
 		s.delete(u);
 		t.commit();
 		s.close();
-	}	
-	
+	}
+
+	/**
+	 * Test case from HHH-1921.  Here the interceptor resets the
+	 * current-state to the same thing as the current db state; this
+	 * causes EntityPersister.findDirty() to return no dirty properties.
+	 */
+	public void testPropertyIntercept2() {
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		User u = new User("Josh", "test");
+		s.persist( u );
+		t.commit();
+		s.close();
+
+		s = openSession(
+				new EmptyInterceptor() {
+					public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) {
+						currentState[0] = "test";
+						return true;
+					}
+				}
+		);
+		t = s.beginTransaction();
+		u = ( User ) s.get( User.class, u.getName() );
+		u.setPassword( "nottest" );
+		t.commit();
+		s.close();
+
+		s = openSession();
+		t = s.beginTransaction();
+		u = (User) s.get(User.class, "Josh");
+		assertEquals("test", u.getPassword());
+		s.delete(u);
+		t.commit();
+		s.close();
+
+	}
+
+	public void testComponentInterceptor() {
+		final int checkPerm = 500;
+		final String checkComment = "generated from interceptor";
+
+		Session s = openSession(
+				new EmptyInterceptor() {
+					public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
+						if ( state[0] == null ) {
+							Image.Details detail = new Image.Details();
+							detail.setPerm1( checkPerm );
+							detail.setComment( checkComment );
+							state[0] = detail;
+						}
+						return true;
+					}
+				}
+		);
+		s.beginTransaction();
+		Image i = new Image();
+		i.setName( "compincomp" );
+		i = ( Image ) s.merge( i );
+		assertNotNull( i.getDetails() );
+		assertEquals( checkPerm, i.getDetails().getPerm1() );
+		assertEquals( checkComment, i.getDetails().getComment() );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		i = ( Image ) s.get( Image.class, i.getId() );
+		assertNotNull( i.getDetails() );
+		assertEquals( checkPerm, i.getDetails().getPerm1() );
+		assertEquals( checkComment, i.getDetails().getComment() );
+		s.delete( i );
+		s.getTransaction().commit();
+		s.close();
+	}
+
 	public void testStatefulIntercept() {
 		final StatefulInterceptor statefulInterceptor = new StatefulInterceptor();
 		Session s = openSession( statefulInterceptor );
@@ -79,7 +157,7 @@
 	}
 	
 	protected String[] getMappings() {
-		return new String[] { "interceptor/User.hbm.xml" };
+		return new String[] { "interceptor/User.hbm.xml", "interceptor/Image.hbm.xml" };
 	}
 
 	public static Test suite() {




More information about the hibernate-commits mailing list