[hibernate-commits] Hibernate SVN: r18708 - in core/trunk/annotations/src: test/java/org/hibernate/test/annotations/derivedidentities/e5 and 3 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri Feb 5 18:33:28 EST 2010


Author: epbernard
Date: 2010-02-05 18:33:28 -0500 (Fri, 05 Feb 2010)
New Revision: 18708

Added:
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/MedicalHistory.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/Person.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/PersonId.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/MedicalHistory.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/Person.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/PersonId.java
Modified:
   core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/ColumnsBuilder.java
Log:
HHH-4848 finish support for derived identity Yeah! More specifically @IdClass on dependent where the @IdClass points to the associated entity id type

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java	2010-02-05 22:02:36 UTC (rev 18707)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java	2010-02-05 23:33:28 UTC (rev 18708)
@@ -683,36 +683,138 @@
 
 		final boolean subclassAndSingleTableStrategy = inheritanceState.getType() == InheritanceType.SINGLE_TABLE
 				&& inheritanceState.hasParents();
-		//process idclass if any
-		Set<String> idProperties = new HashSet<String>();
+		Set<String> idPropertiesIfIdClass = new HashSet<String>();
+		boolean isIdClass = mapAsIdClass(
+				inheritanceStatePerClass,
+				inheritanceState,
+				persistentClass,
+				entityBinder,
+				propertyHolder,
+				elementsToProcess,
+				idPropertiesIfIdClass,
+				mappings
+		);
+
+		if (!isIdClass) {
+			entityBinder.setWrapIdsInEmbeddedComponents( elementsToProcess.getIdPropertyCount() > 1 );
+		}
+
+		processIdPropertiesIfNotAlready(
+				inheritanceStatePerClass,
+				mappings,
+				persistentClass,
+				entityBinder,
+				propertyHolder,
+				classGenerators,
+				elementsToProcess,
+				subclassAndSingleTableStrategy,
+				idPropertiesIfIdClass
+		);
+
+		if ( !inheritanceState.hasParents() ) {
+			final RootClass rootClass = (RootClass) persistentClass;
+			mappings.addSecondPass( new CreateKeySecondPass( rootClass ) );
+		}
+		else {
+			superEntity.addSubclass( (Subclass) persistentClass );
+		}
+
+		mappings.addClass( persistentClass );
+
+		//Process secondary tables and complementary definitions (ie o.h.a.Table)
+		mappings.addSecondPass( new SecondaryTableSecondPass( entityBinder, propertyHolder, clazzToProcess ) );
+
+		//add process complementary Table definition (index & all)
+		entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) );
+		entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) );
+
+	}
+
+	private static void processIdPropertiesIfNotAlready(Map<XClass, InheritanceState> inheritanceStatePerClass, ExtendedMappings mappings, PersistentClass persistentClass, EntityBinder entityBinder, PropertyHolder propertyHolder, HashMap<String, IdGenerator> classGenerators, InheritanceState.ElementsToProcess elementsToProcess, boolean subclassAndSingleTableStrategy, Set<String> idPropertiesIfIdClass) {
+		Set<String> missingIdProperties = new HashSet<String>( idPropertiesIfIdClass );
+		for ( PropertyData propertyAnnotatedElement : elementsToProcess.getElements() ) {
+			String propertyName = propertyAnnotatedElement.getPropertyName();
+			if ( !idPropertiesIfIdClass.contains( propertyName ) ) {
+				processElementAnnotations(
+						propertyHolder,
+						subclassAndSingleTableStrategy ?
+								Nullability.FORCED_NULL :
+								Nullability.NO_CONSTRAINT,
+						propertyAnnotatedElement, classGenerators, entityBinder,
+						false, false, false, mappings, inheritanceStatePerClass
+				);
+			}
+			else {
+				missingIdProperties.remove( propertyName );
+			}
+		}
+
+		if ( missingIdProperties.size() != 0 ) {
+			StringBuilder missings = new StringBuilder();
+			for (String property : missingIdProperties) {
+				missings.append( property ).append( ", " );
+			}
+			throw new AnnotationException(
+					"Unable to find properties ("
+							+ missings.substring( 0, missings.length() - 2 )
+							+ ") in entity annotated with @IdClass:" + persistentClass.getEntityName()
+			);
+		}
+	}
+
+	private static boolean mapAsIdClass(Map<XClass, InheritanceState> inheritanceStatePerClass, InheritanceState inheritanceState, PersistentClass persistentClass, EntityBinder entityBinder, PropertyHolder propertyHolder, InheritanceState.ElementsToProcess elementsToProcess, Set<String> idPropertiesIfIdClass, ExtendedMappings mappings) {
+		/*
+		 * We are looking for @IdClass
+		 * In general we map the id class as identifier using the mapping metadata of the main entity's properties
+		 * and we create an identifier mapper containing the id properties of the main entity
+		 *
+		 * In JPA 2, there is a shortcut if the id class is the Pk of the associated class pointed to by the id
+		 * it ought to be treated as an embedded and not a real IdClass (at least in the Hibernate's internal way
+		 */
 		XClass classWithIdClass = inheritanceState.getClassWithIdClass(false);
 		if ( classWithIdClass != null ) {
 			IdClass idClass = classWithIdClass.getAnnotation( IdClass.class );
 			XClass compositeClass = mappings.getReflectionManager().toXClass( idClass.value() );
-			boolean isComponent = true;
-			AccessType propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
-			String generatorType = "assigned";
-			String generator = BinderHelper.ANNOTATION_STRING_DEFAULT;
 			PropertyData inferredData = new PropertyPreloadedData(
 					entityBinder.getPropertyAccessType(), "id", compositeClass
 			);
 			PropertyData baseInferredData = new PropertyPreloadedData(
                   entityBinder.getPropertyAccessType(), "id", classWithIdClass
             );
-			HashMap<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();
+			AccessType propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
+			//In JPA 2, there is a shortcut if the IdClass is the Pk of the associated class pointed to by the id
+			//it ought to be treated as an embedded and not a real IdClass (at least in the Hibernate's internal way
+			final boolean isFakeIdClass = isIdClassPkOfTheAssociatedEntity(
+					elementsToProcess,
+					compositeClass,
+					inferredData,
+					baseInferredData,
+					propertyAccessor,
+					inheritanceStatePerClass,
+					mappings
+			);
+
+			if ( isFakeIdClass ) {
+				return false;
+			}
+
+			boolean isComponent = true;
+			String generatorType = "assigned";
+			String generator = BinderHelper.ANNOTATION_STRING_DEFAULT;
+
 			boolean ignoreIdAnnotations = entityBinder.isIgnoreIdAnnotations();
 			entityBinder.setIgnoreIdAnnotations( true );
 			propertyHolder.setInIdClass( true );
-			bindId(
+			bindIdClass(
 					generatorType,
 					generator,
 					inferredData,
 					baseInferredData,
 					null,
 					propertyHolder,
-					localGenerators,
 					isComponent,
-					propertyAccessor, entityBinder,
+					propertyAccessor,
+					entityBinder,
 					true,
 					false,
 					mappings,
@@ -723,27 +825,28 @@
 					propertyAccessor, "_identifierMapper", compositeClass
 			);
 			Component mapper = fillComponent(
-					propertyHolder,
-					inferredData,
-					baseInferredData,
-					propertyAccessor,
-					false,
-					entityBinder,
-					true,
-					true,
-					false,
-					mappings,
-					inheritanceStatePerClass
+				propertyHolder,
+				inferredData,
+				baseInferredData,
+				propertyAccessor,
+				false,
+				entityBinder,
+				true,
+				true,
+				false,
+				mappings,
+				inheritanceStatePerClass
 			);
 			entityBinder.setIgnoreIdAnnotations( ignoreIdAnnotations );
 			persistentClass.setIdentifierMapper( mapper );
 
 			//If id definition is on a mapped superclass, update the mapping
-			final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(
-					inferredData.getDeclaringClass(),
-					inheritanceStatePerClass,
-					mappings
-			);
+			final org.hibernate.mapping.MappedSuperclass superclass =
+					BinderHelper.getMappedSuperclassOrNull(
+							inferredData.getDeclaringClass(),
+							inheritanceStatePerClass,
+							mappings
+					);
 			if (superclass != null) {
 				superclass.setDeclaredIdentifierMapper(mapper);
 			}
@@ -764,60 +867,50 @@
 
 			Iterator properties = mapper.getPropertyIterator();
 			while ( properties.hasNext() ) {
-				idProperties.add( ( (Property) properties.next() ).getName() );
+				idPropertiesIfIdClass.add( ( (Property) properties.next() ).getName() );
 			}
+			return true;
 		}
 		else {
-			entityBinder.setWrapIdsInEmbeddedComponents( elementsToProcess.getIdPropertyCount() > 1 );
+			return false;
 		}
-		Set<String> missingIdProperties = new HashSet<String>( idProperties );
-		for (PropertyData propertyAnnotatedElement : elementsToProcess.getElements() ) {
-			String propertyName = propertyAnnotatedElement.getPropertyName();
-			if ( !idProperties.contains( propertyName ) ) {
-				processElementAnnotations(
-						propertyHolder,
-						subclassAndSingleTableStrategy ?
-								Nullability.FORCED_NULL :
-								Nullability.NO_CONSTRAINT,
-						propertyAnnotatedElement.getProperty(),
-						propertyAnnotatedElement, classGenerators, entityBinder,
-						false, false, false, mappings, inheritanceStatePerClass
-				);
+	}
+
+	private static boolean isIdClassPkOfTheAssociatedEntity(
+			InheritanceState.ElementsToProcess elementsToProcess,
+			XClass compositeClass,
+			PropertyData inferredData,
+			PropertyData baseInferredData,
+			AccessType propertyAccessor,
+			Map<XClass, InheritanceState> inheritanceStatePerClass,
+			ExtendedMappings mappings) {
+		if ( elementsToProcess.getIdPropertyCount() == 1 ) {
+			final PropertyData idPropertyOnBaseClass = getUniqueIdPropertyFromBaseClass(
+					inferredData, baseInferredData, propertyAccessor, mappings
+			);
+			final InheritanceState state = inheritanceStatePerClass.get( idPropertyOnBaseClass.getClassOrElement() );
+			if (state == null) {
+				return false; //while it is likely a user error, let's consider it is something that might happen
 			}
+			final XClass associatedClassWithIdClass = state.getClassWithIdClass( true );
+			if ( associatedClassWithIdClass == null ) {
+				//we cannot know for sure here unless we try and find the @EmbeddedId
+				//Let's not do this thorough checking but do some extra validation
+				final XProperty property = idPropertyOnBaseClass.getProperty();
+				return property.isAnnotationPresent( ManyToOne.class )
+						|| property.isAnnotationPresent( OneToOne.class );
+
+			}
 			else {
-				missingIdProperties.remove( propertyName );
+				final XClass idClass = mappings.getReflectionManager().toXClass(
+						associatedClassWithIdClass.getAnnotation( IdClass.class ).value()
+				);
+				return idClass.equals( compositeClass );
 			}
 		}
-
-		if ( missingIdProperties.size() != 0 ) {
-			StringBuilder missings = new StringBuilder();
-			for (String property : missingIdProperties) {
-				missings.append( property ).append( ", " );
-			}
-			throw new AnnotationException(
-					"Unable to find properties ("
-							+ missings.substring( 0, missings.length() - 2 )
-							+ ") in entity annotated with @IdClass:" + persistentClass.getEntityName()
-			);
-		}
-
-		if ( !inheritanceState.hasParents() ) {
-			final RootClass rootClass = (RootClass) persistentClass;
-			mappings.addSecondPass( new CreateKeySecondPass( rootClass ) );
-		}
 		else {
-			superEntity.addSubclass( (Subclass) persistentClass );
+			return false;
 		}
-
-		mappings.addClass( persistentClass );
-
-		//Process secondary tables and complementary definitions (ie o.h.a.Table)
-		mappings.addSecondPass( new SecondaryTableSecondPass( entityBinder, propertyHolder, clazzToProcess ) );
-
-		//add process complementary Table definition (index & all)
-		entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) );
-		entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) );
-
 	}
 
 	private static Cache determineCacheSettings(XClass clazzToProcess, ExtendedMappings mappings) {
@@ -1230,7 +1323,7 @@
 	 * Process annotation of a particular property
 	 */
 	private static void processElementAnnotations(
-			PropertyHolder propertyHolder, Nullability nullability, XProperty property,
+			PropertyHolder propertyHolder, Nullability nullability,
 			PropertyData inferredData, HashMap<String, IdGenerator> classGenerators,
 			EntityBinder entityBinder, boolean isIdentifierMapper,
 			boolean isComponentEmbedded, boolean inSecondPass, ExtendedMappings mappings,
@@ -1246,6 +1339,7 @@
 				"Processing annotations of {}.{}", propertyHolder.getEntityName(), inferredData.getPropertyName()
 		);
 
+		final XProperty property = inferredData.getProperty();
 		if ( property.isAnnotationPresent( Parent.class ) ) {
 			if ( propertyHolder.isComponent() ) {
 				propertyHolder.setParentProperty( property.getName() );
@@ -1794,7 +1888,7 @@
 						final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(
 								isId, propertyHolder, property.getName(), mappings
 						);
-						HashMap<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) classGenerators.clone();
+						Map<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) classGenerators.clone();
 						final IdGenerator foreignGenerator = new IdGenerator();
 						foreignGenerator.setIdentifierGeneratorStrategy( "assigned" );
 						foreignGenerator.setName( "Hibernate-local--foreign generator" );
@@ -2061,7 +2155,7 @@
 				inferredData, propertyHolder, mappings
 		);
 
-		final XClass entityXClass = inferredData.getPropertyClass();
+		final XClass xClassProcessed = inferredData.getPropertyClass();
 		List<PropertyData> classElements = new ArrayList<PropertyData>();
 		XClass returnedClassOrElement = inferredData.getClassOrElement();
 
@@ -2069,11 +2163,11 @@
 		Map<String, PropertyData> orderedBaseClassElements = new HashMap<String, PropertyData>();
 		XClass baseReturnedClassOrElement;
 		if(baseInferredData != null) {
-		   baseClassElements = new ArrayList<PropertyData>();
-		   baseReturnedClassOrElement = baseInferredData.getClassOrElement();
-		   bindTypeDefs(baseReturnedClassOrElement, mappings);
-	       PropertyContainer propContainer = new PropertyContainer( baseReturnedClassOrElement, entityXClass );
-		   addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );
+			baseClassElements = new ArrayList<PropertyData>();
+			baseReturnedClassOrElement = baseInferredData.getClassOrElement();
+			bindTypeDefs(baseReturnedClassOrElement, mappings);
+			PropertyContainer propContainer = new PropertyContainer( baseReturnedClassOrElement, xClassProcessed );
+			addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );
 			for (PropertyData element : baseClassElements) {
 				orderedBaseClassElements.put( element.getPropertyName(), element );
 			}
@@ -2081,39 +2175,43 @@
 
 		//embeddable elements can have type defs
 		bindTypeDefs(returnedClassOrElement, mappings);
-		PropertyContainer propContainer = new PropertyContainer( returnedClassOrElement, entityXClass );
+		PropertyContainer propContainer = new PropertyContainer( returnedClassOrElement, xClassProcessed );
 		addElementsOfClass( classElements, propertyAccessor, propContainer, mappings);
 
 		//add elements of the embeddable superclass
-		XClass superClass = entityXClass.getSuperclass();
+		XClass superClass = xClassProcessed.getSuperclass();
 		while ( superClass != null && superClass.isAnnotationPresent( MappedSuperclass.class ) ) {
 			//FIXME: proper support of typevariables incl var resolved at upper levels
-			propContainer = new PropertyContainer( superClass, entityXClass );
+			propContainer = new PropertyContainer( superClass, xClassProcessed );
 			addElementsOfClass( classElements, propertyAccessor, propContainer, mappings );
 			superClass = superClass.getSuperclass();
 		}
 		if ( baseClassElements != null ) {
 			//useful to avoid breaking pre JPA 2 mappings
-			if ( !hasAnnotationsOnIdClass( entityXClass ) ) {
+			if ( !hasAnnotationsOnIdClass( xClassProcessed ) ) {
 				for ( int i = 0; i < classElements.size(); i++ ) {
 					final PropertyData idClassPropertyData = classElements.get( i );
 					final PropertyData entityPropertyData = orderedBaseClassElements.get( idClassPropertyData.getPropertyName() );
-					//FIXME 
-					if ( entityPropertyData != null ) {
-						if ( propertyHolder.isInIdClass() ) {
-							if ( entityPropertyData.getProperty().isAnnotationPresent( ManyToOne.class )
-									|| entityPropertyData.getProperty().isAnnotationPresent( OneToOne.class ) ) {
-								//don't replace here as we need to use the actual original return type
-								//the annotation overriding will be dealt with by a mechanism similar to @MapsId
-							}
-							else {
-								classElements.set( i, entityPropertyData );  //this works since they are in the same order
-							}
+					if ( propertyHolder.isInIdClass() ) {
+						if (entityPropertyData == null) {
+							throw new AnnotationException (
+									"Property of @IdClass not found in entity "
+											+ baseInferredData.getPropertyClass().getName() + ": "
+											+ idClassPropertyData.getPropertyName() 
+							);
 						}
+						if ( entityPropertyData.getProperty().isAnnotationPresent( ManyToOne.class )
+								|| entityPropertyData.getProperty().isAnnotationPresent( OneToOne.class ) ) {
+							//don't replace here as we need to use the actual original return type
+							//the annotation overriding will be dealt with by a mechanism similar to @MapsId
+						}
 						else {
 							classElements.set( i, entityPropertyData );  //this works since they are in the same order
 						}
 					}
+					else {
+						classElements.set( i, entityPropertyData );  //this works since they are in the same order
+					}
 				}
 			}
 		}
@@ -2122,7 +2220,7 @@
 					subHolder, isNullable ?
 					Nullability.NO_CONSTRAINT :
 					Nullability.FORCED_NOT_NULL,
-					propertyAnnotatedElement.getProperty(), propertyAnnotatedElement,
+					propertyAnnotatedElement,
 					new HashMap<String, IdGenerator>(), entityBinder, isIdentifierMapper, isComponentEmbedded,
 					inSecondPass, mappings, inheritanceStatePerClass
 			);
@@ -2131,7 +2229,7 @@
 			if(property.isAnnotationPresent(GeneratedValue.class) &&
 			      property.isAnnotationPresent(Id.class) ) {
 			   //clone classGenerator and override with local values
-			   HashMap<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();
+			   Map<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();
 			   localGenerators.putAll( buildLocalGenerators( property, mappings ) );
 
 			   GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
@@ -2161,10 +2259,9 @@
 		return comp;
 	}
 
-    private static void bindId(
+    private static void bindIdClass(
           String generatorType, String generatorName, PropertyData inferredData,
           PropertyData baseInferredData, Ejb3Column[] columns, PropertyHolder propertyHolder,
-          Map<String, IdGenerator> localGenerators,
           boolean isComposite,
           AccessType propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
           boolean isIdentifierMapper, ExtendedMappings mappings,
@@ -2185,6 +2282,7 @@
 		String persistentClassName = rootClass.getClassName();
 		SimpleValue id;
 		final String propertyName = inferredData.getPropertyName();
+		HashMap<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();
 		if ( isComposite ) {
 			id = fillComponent(
 					propertyHolder, inferredData, baseInferredData, propertyAccessor,
@@ -2203,6 +2301,8 @@
 			setupComponentTuplizer( property, componentId );
 		}
 		else {
+			//TODO I think this branch is never used. Remove.
+
 			for (Ejb3Column column : columns) {
 				column.forceNotNull(); //this is an id
 			}
@@ -2244,6 +2344,16 @@
 		}
 	}
 
+	private static PropertyData getUniqueIdPropertyFromBaseClass(PropertyData inferredData, PropertyData baseInferredData, AccessType propertyAccessor, ExtendedMappings mappings) {
+		List<PropertyData> baseClassElements = new ArrayList<PropertyData>();
+		XClass baseReturnedClassOrElement = baseInferredData.getClassOrElement();
+		PropertyContainer propContainer = new PropertyContainer( baseReturnedClassOrElement, inferredData.getPropertyClass() );
+		addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );
+		//Id properties are on top and there is only one
+		final PropertyData idPropertyOnBaseClass = baseClassElements.get( 0 );
+		return idPropertyOnBaseClass;
+	}
+
 	private static void setupComponentTuplizer(XProperty property, Component component) {
 		if ( property == null ) return;
 		if ( property.isAnnotationPresent( Tuplizers.class ) ) {

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/ColumnsBuilder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/ColumnsBuilder.java	2010-02-05 22:02:36 UTC (rev 18707)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/ColumnsBuilder.java	2010-02-05 23:33:28 UTC (rev 18708)
@@ -185,11 +185,20 @@
 		Ejb3Column[] result = columns;
 		final PropertyData overridingProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId( isId, propertyHolder, property.getName(), mappings );
 		if ( overridingProperty != null ) {
-			result = buildExplicitJoinColumns( overridingProperty.getProperty(), overridingProperty );
-			if (result == null) {
-				result = buildDefaultJoinColumnsForXToOne( overridingProperty.getProperty(), overridingProperty);
-			}
+			result = buildExcplicitOrDefaultJoinColumn( overridingProperty );
 		}
 		return result;
 	}
+
+	/**
+	 * useful to override a column either by @MapsId or by @IdClass
+	 */
+	Ejb3Column[] buildExcplicitOrDefaultJoinColumn(PropertyData overridingProperty) {
+		Ejb3Column[] result;
+		result = buildExplicitJoinColumns( overridingProperty.getProperty(), overridingProperty );
+		if (result == null) {
+			result = buildDefaultJoinColumnsForXToOne( overridingProperty.getProperty(), overridingProperty);
+		}
+		return result;
+	}
 }

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/DerivedIdentityIdClassParentSameIdTypeIdClassDepTest.java	2010-02-05 23:33:28 UTC (rev 18708)
@@ -0,0 +1,46 @@
+package org.hibernate.test.annotations.derivedidentities.e5.a;
+
+import org.hibernate.Session;
+import org.hibernate.junit.FailureExpected;
+import org.hibernate.test.annotations.TestCase;
+import org.hibernate.test.util.SchemaUtil;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class DerivedIdentityIdClassParentSameIdTypeIdClassDepTest extends TestCase {
+	
+	public void testOneToOneExplicitJoinColumn() throws Exception {
+		assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", getCfg() ) );
+		assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", getCfg() ) );
+		assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", getCfg() ) );
+		Person e = new Person();
+		e.firstName = "Emmanuel";
+		e.lastName = "Bernard";
+		Session s = openSession(  );
+		s.getTransaction().begin();
+		s.persist( e );
+		MedicalHistory d = new MedicalHistory();
+		d.patient = e;
+		s.persist( d );
+		s.flush();
+		s.clear();
+		PersonId pId = new PersonId();
+		pId.firstName = e.firstName;
+		pId.lastName = e.lastName;
+		d = (MedicalHistory) s.get( MedicalHistory.class, pId);
+		assertEquals( pId.firstName, d.patient.firstName );
+		s.delete( d );
+		s.delete( d.patient );
+		s.getTransaction().rollback();
+		s.close();
+	}
+
+	@Override
+	protected Class<?>[] getAnnotatedClasses() {
+		return new Class<?>[] {
+				MedicalHistory.class,
+				Person.class
+		};
+	}
+}

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/MedicalHistory.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/MedicalHistory.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/MedicalHistory.java	2010-02-05 23:33:28 UTC (rev 18708)
@@ -0,0 +1,24 @@
+package org.hibernate.test.annotations.derivedidentities.e5.a;
+
+import java.io.Serializable;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.OneToOne;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+ at IdClass(PersonId.class)
+public class MedicalHistory implements Serializable {
+	@Id
+	@JoinColumns({
+			@JoinColumn(name = "FK1", referencedColumnName = "firstName"),
+			@JoinColumn(name = "FK2", referencedColumnName = "lastName")
+	})
+	@OneToOne
+	Person patient;
+}

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/Person.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/Person.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/Person.java	2010-02-05 23:33:28 UTC (rev 18708)
@@ -0,0 +1,16 @@
+package org.hibernate.test.annotations.derivedidentities.e5.a;
+
+import java.io.Serializable;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+ at IdClass(PersonId.class)
+public class Person {
+	@Id String firstName;
+	@Id String lastName;
+}

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/PersonId.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/PersonId.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e5/a/PersonId.java	2010-02-05 23:33:28 UTC (rev 18708)
@@ -0,0 +1,11 @@
+package org.hibernate.test.annotations.derivedidentities.e5.a;
+
+import java.io.Serializable;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class PersonId implements Serializable {
+	String firstName;
+	String lastName;
+}

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest.java	2010-02-05 23:33:28 UTC (rev 18708)
@@ -0,0 +1,47 @@
+package org.hibernate.test.annotations.derivedidentities.e6.a;
+
+import org.hibernate.Session;
+import org.hibernate.junit.FailureExpected;
+import org.hibernate.test.annotations.TestCase;
+import org.hibernate.test.util.SchemaUtil;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class DerivedIdentityEmbeddedIdParentSameIdTypeIdClassDepTest extends TestCase {
+
+	public void testOneToOneExplicitJoinColumn() throws Exception {
+		assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK1", getCfg() ) );
+		assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK2", getCfg() ) );
+		assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "firstname", getCfg() ) );
+		Person e = new Person();
+		e.id = new PersonId();
+		e.id.firstName = "Emmanuel";
+		e.id.lastName = "Bernard";
+		Session s = openSession(  );
+		s.getTransaction().begin();
+		s.persist( e );
+		MedicalHistory d = new MedicalHistory();
+		d.patient = e;
+		s.persist( d );
+		s.flush();
+		s.clear();
+		PersonId pId = new PersonId();
+		pId.firstName = e.id.firstName;
+		pId.lastName = e.id.lastName;
+		d = (MedicalHistory) s.get( MedicalHistory.class, pId );
+		assertEquals( pId.firstName, d.patient.id.firstName );
+		s.delete( d );
+		s.delete( d.patient );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	@Override
+	protected Class<?>[] getAnnotatedClasses() {
+		return new Class<?>[] {
+				MedicalHistory.class,
+				Person.class
+		};
+	}
+}
\ No newline at end of file

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/MedicalHistory.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/MedicalHistory.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/MedicalHistory.java	2010-02-05 23:33:28 UTC (rev 18708)
@@ -0,0 +1,26 @@
+package org.hibernate.test.annotations.derivedidentities.e6.a;
+
+import java.io.Serializable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.MapsId;
+import javax.persistence.OneToOne;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+ at IdClass(PersonId.class)
+public class MedicalHistory implements Serializable {
+	@Id
+	@JoinColumns({
+			@JoinColumn(name = "FK1", referencedColumnName = "firstName"),
+			@JoinColumn(name = "FK2", referencedColumnName = "lastName")
+	})
+	@OneToOne
+	Person patient;
+}

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/Person.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/Person.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/Person.java	2010-02-05 23:33:28 UTC (rev 18708)
@@ -0,0 +1,13 @@
+package org.hibernate.test.annotations.derivedidentities.e6.a;
+
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class Person {
+	@EmbeddedId
+	PersonId id;
+}

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/PersonId.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/PersonId.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e6/a/PersonId.java	2010-02-05 23:33:28 UTC (rev 18708)
@@ -0,0 +1,13 @@
+package org.hibernate.test.annotations.derivedidentities.e6.a;
+
+import java.io.Serializable;
+import javax.persistence.Embeddable;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Embeddable
+public class PersonId implements Serializable {
+	String firstName;
+	String lastName;
+}



More information about the hibernate-commits mailing list