[hibernate-commits] Hibernate SVN: r18767 - in core/trunk: core/src/main/java/org/hibernate/event/def and 1 other directory.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Feb 10 12:38:59 EST 2010


Author: steve.ebersole at jboss.com
Date: 2010-02-10 12:38:59 -0500 (Wed, 10 Feb 2010)
New Revision: 18767

Modified:
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/MedicalHistory.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/Person.java
   core/trunk/core/src/main/java/org/hibernate/event/def/DefaultPersistEventListener.java
Log:
HHH-4902 - Handle JPA 2 requirement of setting id attribute to non-null with its equivalent of foreign-generator


Modified: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java	2010-02-10 17:34:16 UTC (rev 18766)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepMapsIdTest.java	2010-02-10 17:38:59 UTC (rev 18767)
@@ -1,7 +1,11 @@
 package org.hibernate.test.annotations.derivedidentities.e4.b;
 
 import java.util.Date;
+import java.util.List;
 
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+
 import org.hibernate.Session;
 import org.hibernate.test.annotations.TestCase;
 import org.hibernate.test.util.SchemaUtil;
@@ -61,6 +65,45 @@
 		s.close();
 	}
 
+	public void testExplicitlyAssignedDependentIdAttributeValue() {
+		// even though the id is by definition generated (using the "foreign" strategy), JPA
+		// still does allow manually setting the generated id attribute value which providers
+		// are expected to promptly disregard :?
+		Session s = openSession();
+		s.beginTransaction();
+		Person person = new Person( "123456789" );
+		MedicalHistory medicalHistory = new MedicalHistory( "987654321", person );
+		s.persist( person );
+		s.persist( medicalHistory );
+		s.getTransaction().commit();
+		s.close();
+
+		// again, even though we specified an id value of "987654321" prior to persist,
+		// Hibernate should have replaced that with the "123456789" from the associated
+		// person
+		assertEquals( person.ssn, medicalHistory.patient.ssn );
+		assertEquals( person, medicalHistory.patient );
+		assertEquals( person.ssn, medicalHistory.id );
+
+		s = openSession();
+		s.beginTransaction();
+		// Should return null...
+		MedicalHistory separateMedicalHistory = (MedicalHistory) s.get( MedicalHistory.class, "987654321" );
+		assertNull( separateMedicalHistory );
+		// Now we should find it...
+		separateMedicalHistory = (MedicalHistory) s.get( MedicalHistory.class, "123456789" );
+		assertNotNull( separateMedicalHistory );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		s.delete( medicalHistory );
+		s.delete( person );
+		s.getTransaction().commit();
+		s.close();
+	}
+
 	@Override
 	protected Class<?>[] getAnnotatedClasses() {
 		return new Class<?>[] {

Modified: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/MedicalHistory.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/MedicalHistory.java	2010-02-10 17:34:16 UTC (rev 18766)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/MedicalHistory.java	2010-02-10 17:38:59 UTC (rev 18767)
@@ -1,6 +1,7 @@
 package org.hibernate.test.annotations.derivedidentities.e4.b;
 
 import java.util.Date;
+import javax.persistence.CascadeType;
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
@@ -16,11 +17,20 @@
 public class MedicalHistory {
 
 	@Id String id; // overriding not allowed ... // default join column name is overridden @MapsId
+
+	@MapsId
+	@JoinColumn(name = "FK")
+    @OneToOne(cascade= CascadeType.ALL)
+	Person patient;
+
 	@Temporal(TemporalType.DATE)
 	Date lastupdate;
 
-	@JoinColumn(name = "FK")
-	@MapsId
-	@OneToOne
-	Person patient;
+	public MedicalHistory() {
+	}
+
+	public MedicalHistory(String id, Person patient) {
+		this.id = id;
+		this.patient = patient;
+	}
 }

Modified: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/Person.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/Person.java	2010-02-10 17:34:16 UTC (rev 18766)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/Person.java	2010-02-10 17:38:59 UTC (rev 18767)
@@ -10,4 +10,11 @@
 public class Person {
 	@Id
 	String ssn;
+
+	public Person() {
+	}
+
+	public Person(String ssn) {
+		this.ssn = ssn;
+	}
 }
\ No newline at end of file

Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultPersistEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultPersistEventListener.java	2010-02-10 17:34:16 UTC (rev 18766)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultPersistEventListener.java	2010-02-10 17:38:59 UTC (rev 18767)
@@ -1,10 +1,10 @@
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
  * indicated by the @author tags or express copyright attribution
  * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
+ * distributed under license by Red Hat Inc.
  *
  * This copyrighted material is made available to anyone wishing to use, modify,
  * copy, or redistribute it subject to the terms and conditions of the GNU
@@ -20,7 +20,6 @@
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
  * Boston, MA  02110-1301  USA
- *
  */
 package org.hibernate.event.def;
 
@@ -32,10 +31,12 @@
 import org.hibernate.ObjectDeletedException;
 import org.hibernate.PersistentObjectException;
 import org.hibernate.engine.CascadingAction;
+import org.hibernate.engine.EntityEntry;
 import org.hibernate.event.EventSource;
 import org.hibernate.event.PersistEvent;
 import org.hibernate.event.PersistEventListener;
 import org.hibernate.engine.SessionImplementor;
+import org.hibernate.id.ForeignGenerator;
 import org.hibernate.persister.entity.EntityPersister;
 import org.hibernate.proxy.HibernateProxy;
 import org.hibernate.proxy.LazyInitializer;
@@ -48,7 +49,6 @@
  * @author Gavin King
  */
 public class DefaultPersistEventListener extends AbstractSaveEventListener implements PersistEventListener {
-
 	private static final Logger log = LoggerFactory.getLogger(DefaultPersistEventListener.class);
 
 	/** 
@@ -69,19 +69,18 @@
 	 * @throws HibernateException
 	 */
 	public void onPersist(PersistEvent event, Map createCache) throws HibernateException {
-			
 		final SessionImplementor source = event.getSession();
 		final Object object = event.getObject();
 		
 		final Object entity;
-		if (object instanceof HibernateProxy) {
+		if ( object instanceof HibernateProxy ) {
 			LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
 			if ( li.isUninitialized() ) {
-				if ( li.getSession()==source ) {
+				if ( li.getSession() == source ) {
 					return; //NOTE EARLY EXIT!
 				}
 				else {
-					throw new PersistentObjectException("uninitialized proxy passed to persist()");
+					throw new PersistentObjectException( "uninitialized proxy passed to persist()" );
 				}
 			}
 			entity = li.getImplementation();
@@ -89,32 +88,58 @@
 		else {
 			entity = object;
 		}
-		
-		int entityState = getEntityState( 
-				entity, 
-				event.getEntityName(), 
-				source.getPersistenceContext().getEntry(entity), 
-				source 
-			);
-		
-		switch (entityState) {
-			case DETACHED: 
-				throw new PersistentObjectException( 
-						"detached entity passed to persist: " + 
-						getLoggableName( event.getEntityName(), entity ) 
-					);
+
+		final String entityName;
+		if ( event.getEntityName() != null ) {
+			entityName = event.getEntityName();
+		}
+		else {
+			entityName = source.bestGuessEntityName( entity );
+			event.setEntityName( entityName );
+		}
+
+		final EntityEntry entityEntry = source.getPersistenceContext().getEntry( entity );
+		int entityState = getEntityState( entity, entityName, entityEntry, source );
+		if ( entityState == DETACHED ) {
+			// JPA 2, in its version of a "foreign generated", allows the id attribute value
+			// to be manually set by the user, even though this manual value is irrelevant.
+			// The issue is that this causes problems with the Hibernate unsaved-value strategy
+			// which comes into play here in determining detached/transient state.
+			//
+			// Detect if we have this situation and if so null out the id value and calculate the
+			// entity state again.
+
+			// NOTE: entityEntry must be null to get here, so we cannot use any of its values
+			EntityPersister persister = source.getFactory().getEntityPersister( entityName );
+			if ( ForeignGenerator.class.isInstance( persister.getIdentifierGenerator() ) ) {
+				if ( log.isDebugEnabled() ) {
+					if ( persister.getIdentifier( entity, source ) != null ) {
+						log.debug( "Resetting entity id attribute to null for foreign generator" );
+					}
+				}
+				persister.setIdentifier( entity, null, source );
+				entityState = getEntityState( entity, entityName, entityEntry, source );
+			}
+		}
+
+		switch ( entityState ) {
+			case DETACHED:
+				throw new PersistentObjectException(
+						"detached entity passed to persist: " +
+								getLoggableName( event.getEntityName(), entity )
+				);
 			case PERSISTENT:
-				entityIsPersistent(event, createCache);
+				entityIsPersistent( event, createCache );
 				break;
 			case TRANSIENT:
-				entityIsTransient(event, createCache);
+				entityIsTransient( event, createCache );
 				break;
-			default: 
-				throw new ObjectDeletedException( 
-						"deleted entity passed to persist", 
-						null, 
+			default:
+				throw new ObjectDeletedException(
+						"deleted entity passed to persist",
+						null,
 						getLoggableName( event.getEntityName(), entity )
-					);
+				);
 		}
 
 	}



More information about the hibernate-commits mailing list