[hibernate-commits] Hibernate SVN: r18619 - in core/trunk/annotations/src: main/java/org/hibernate/cfg/annotations and 4 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Mon Jan 25 12:19:07 EST 2010


Author: epbernard
Date: 2010-01-25 12:19:05 -0500 (Mon, 25 Jan 2010)
New Revision: 18619

Added:
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/Dependent.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/Employee.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/FinancialHistory.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/MedicalHistory.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java
   core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Simple.java
Modified:
   core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/Version.java
Log:
HHH-4529 support for derived entity id as a XToOne pointing to the master entity
HHH-4840 support for Core style embedded id (after all these years :) )

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java	2010-01-25 16:23:59 UTC (rev 18618)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -625,10 +625,10 @@
 		HashMap<String, IdGenerator> classGenerators = buildLocalGenerators( clazzToProcess, mappings );
 
 		// check properties
-		List<PropertyData> elements =
-				getElementsToProcess(
-						persistentClass, clazzToProcess, inheritanceStatePerClass, entityBinder, mappings
-				);
+		final ElementsToProcess elementsToProcess = getElementsToProcess(
+				persistentClass, clazzToProcess, inheritanceStatePerClass, entityBinder, mappings
+		);
+		
 		final boolean subclassAndSingleTableStrategy = inheritanceState.getType() == InheritanceType.SINGLE_TABLE
 				&& inheritanceState.hasParents();
 		//process idclass if any
@@ -674,7 +674,9 @@
 					isComponent,
 					propertyAccessor, entityBinder,
 					true,
-					false, mappings, inheritanceStatePerClass
+					false,
+					mappings,
+					inheritanceStatePerClass
 			);
 			inferredData = new PropertyPreloadedData(
 					propertyAccessor, "_identifierMapper", compositeClass
@@ -683,9 +685,11 @@
 					propertyHolder,
 					inferredData,
 					baseInferredData,
-					propertyAccessor, false,
+					propertyAccessor,
+					false,
 					entityBinder,
-					true, true,
+					true,
+					true,
 					false, mappings, inheritanceStatePerClass
 			);
 			entityBinder.setIgnoreIdAnnotations( ignoreIdAnnotations );
@@ -720,8 +724,11 @@
 				idProperties.add( ( (Property) properties.next() ).getName() );
 			}
 		}
+		else {
+			entityBinder.setWrapIdsInEmbeddedComponents( elementsToProcess.getIdPropertyCount() > 1 );
+		}
 		Set<String> missingIdProperties = new HashSet<String>( idProperties );
-		for (PropertyData propertyAnnotatedElement : elements) {
+		for (PropertyData propertyAnnotatedElement : elementsToProcess.getElements() ) {
 			String propertyName = propertyAnnotatedElement.getPropertyName();
 			if ( !idProperties.contains( propertyName ) ) {
 				processElementAnnotations(
@@ -979,7 +986,7 @@
 	 * Get the annotated elements, guessing the access type from @Id or @EmbeddedId presence.
 	 * Change EntityBinder by side effect
 	 */
-	private static List<PropertyData> getElementsToProcess(
+	private static ElementsToProcess getElementsToProcess(
 			PersistentClass persistentClass, XClass clazzToProcess,
 			Map<XClass, InheritanceState> inheritanceStatePerClass,
 			EntityBinder entityBinder, ExtendedMappings mappings
@@ -996,23 +1003,41 @@
 
 		List<PropertyData> elements = new ArrayList<PropertyData>();
 		int deep = classesToProcess.size();
-		boolean hasIdentifier = false;
+		int idPropertyCount = 0;
 
 		for ( int index = 0; index < deep; index++ ) {
-			PropertyContainer properyContainer = new PropertyContainer( classesToProcess.get( index ), clazzToProcess );
-			boolean currentHasIdentifier = addElementsOfClass( elements, accessType, properyContainer, mappings );
-			hasIdentifier = hasIdentifier || currentHasIdentifier;
+			PropertyContainer propertyContainer = new PropertyContainer( classesToProcess.get( index ), clazzToProcess );
+			int currentIdPropertyCount = addElementsOfClass( elements, accessType, propertyContainer, mappings );
+			idPropertyCount +=  currentIdPropertyCount;
 		}
 
 		entityBinder.setPropertyAccessType( accessType );
 
-		if ( !hasIdentifier && !inheritanceState.hasParents() ) {
+		if ( idPropertyCount == 0 && !inheritanceState.hasParents() ) {
 			throw new AnnotationException( "No identifier specified for entity: " + clazzToProcess.getName() );
 		}
 
-		return elements;
+		return new ElementsToProcess( elements, idPropertyCount);
 	}
 
+	private static final class ElementsToProcess {
+		private final List<PropertyData> properties;
+		private final int idPropertyCount;
+
+		public List<PropertyData> getElements() {
+			return properties;
+		}
+
+		public int getIdPropertyCount() {
+			return idPropertyCount;
+		}
+
+		private ElementsToProcess(List<PropertyData> properties, int idPropertyCount) {
+			this.properties = properties;
+			this.idPropertyCount = idPropertyCount;
+		}
+	}
+
 	private static AccessType determineDefaultAccessType(XClass annotatedClass, Map<XClass, InheritanceState> inheritanceStatePerClass) {
 		XClass xclass = annotatedClass;
 		while ( xclass != null && !Object.class.getName().equals( xclass.getName() ) ) {
@@ -1207,13 +1232,13 @@
 	 *        strategy is used
 	 * @param propertyContainer Metadata about a class and its properties
 	 * @param mappings Mapping meta data
-	 * @return {@code true} in case an id property was found while iterating the elements of {@code annoatedClass} using
+	 * @return the number of id properties found while iterating the elements of {@code annoatedClass} using
 	 * the determined access strategy, {@code false} otherwise.
 	 */
-	private static boolean addElementsOfClass(
+	private static int addElementsOfClass(
 			List<PropertyData> elements, AccessType defaultAccessType, PropertyContainer propertyContainer, ExtendedMappings mappings
 	) {
-		boolean hasIdentifier = false;
+		int idPropertyCounter = 0;
 		AccessType accessType = defaultAccessType;
 
 		if ( propertyContainer.hasExplicitAccessStrategy() ) {
@@ -1223,21 +1248,21 @@
 		propertyContainer.assertTypesAreResolvable( accessType );
 		Collection<XProperty> properties = propertyContainer.getProperties( accessType );
 		for ( XProperty p : properties ) {
-			final boolean currentHasIdentifier = addProperty(
+			final int currentIdPropertyCounter = addProperty(
 					propertyContainer, p, elements, accessType.getType(), mappings
 			);
-			hasIdentifier = hasIdentifier || currentHasIdentifier;
+			idPropertyCounter += currentIdPropertyCounter;
 		}
-		return hasIdentifier;
+		return idPropertyCounter;
 	}
 
-	private static boolean addProperty(
+	private static int addProperty(
 			PropertyContainer propertyContainer, XProperty property, List<PropertyData> annElts,
 			String propertyAccessor, ExtendedMappings mappings
 	) {
 		final XClass declaringClass = propertyContainer.getDeclaringClass();
 		final XClass entity = propertyContainer.getEntityAtStake();
-		boolean hasIdentifier;
+		int idPropertyCounter = 0;
 		PropertyData propertyAnnotatedElement = new PropertyInferredData(
 				declaringClass, property, propertyAccessor,
 				mappings.getReflectionManager() );
@@ -1249,17 +1274,16 @@
 		final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
 		if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) {
 			annElts.add( 0, propertyAnnotatedElement );
-			hasIdentifier = true;
+			idPropertyCounter++;
 		}
 		else {
 			annElts.add( propertyAnnotatedElement );
-			hasIdentifier = false;
 		}
 		if ( element.isAnnotationPresent( MapsId.class  ) ) {
 			mappings.addPropertyAnnotatedWithMapsId( entity, propertyAnnotatedElement );
 		}
 
-		return hasIdentifier;
+		return idPropertyCounter;
 	}
 
 	/*
@@ -1361,9 +1385,28 @@
 
 		final XClass returnedClass = inferredData.getClassOrElement();
 
+		//prepare PropertyBinder
+		PropertyBinder propertyBinder = new PropertyBinder();
+		propertyBinder.setName( inferredData.getPropertyName() );
+		propertyBinder.setReturnedClassName( inferredData.getTypeName() );
+		propertyBinder.setAccessType( inferredData.getDefaultAccess() );
+		propertyBinder.setHolder( propertyHolder );
+		propertyBinder.setProperty( property );
+		propertyBinder.setReturnedClass( inferredData.getPropertyClass() );
+		propertyBinder.setMappings( mappings );
+		if ( isIdentifierMapper ) {
+			propertyBinder.setInsertable( false );
+			propertyBinder.setUpdatable( false );
+		}
+		propertyBinder.setDeclaringClass( inferredData.getDeclaringClass() );
+		propertyBinder.setEntityBinder( entityBinder );
+		propertyBinder.setInheritanceStatePerClass(inheritanceStatePerClass);
+
 		boolean isId = !entityBinder.isIgnoreIdAnnotations() &&
 				( property.isAnnotationPresent( Id.class )
 						|| property.isAnnotationPresent( EmbeddedId.class ) );
+		propertyBinder.setId( isId );
+
 		if ( property.isAnnotationPresent( Version.class ) ) {
 			if ( isIdentifierMapper ) {
 				throw new AnnotationException(
@@ -1384,19 +1427,14 @@
 			}
 			log.trace( "{} is a version property", inferredData.getPropertyName() );
 			RootClass rootClass = (RootClass) propertyHolder.getPersistentClass();
-			PropertyBinder propBinder = new PropertyBinder();
-			propBinder.setName( inferredData.getPropertyName() );
-			propBinder.setReturnedClassName( inferredData.getTypeName() );
-			propBinder.setLazy( false );
-			propBinder.setAccessType( inferredData.getDefaultAccess() );
-			propBinder.setColumns( columns );
-			propBinder.setHolder( propertyHolder ); //PropertyHolderBuilder.buildPropertyHolder(rootClass)
-			propBinder.setProperty( property );
-			propBinder.setReturnedClass( inferredData.getPropertyClass() );
-			propBinder.setMappings( mappings );
-			propBinder.setDeclaringClass( inferredData.getDeclaringClass() );
-			Property prop = propBinder.makePropertyValueAndBind();
-			propBinder.getSimpleValueBinder().setVersion(true);
+//			PropertyBinder propBinder = new PropertyBinder();
+//			propBinder.setName( inferredData.getPropertyName() );
+//			propBinder.setReturnedClassName( inferredData.getTypeName() );
+//			propBinder.setLazy( false );
+//			propBinder.setAccessType( inferredData.getDefaultAccess() );
+			propertyBinder.setColumns( columns );
+			Property prop = propertyBinder.makePropertyValueAndBind();
+			propertyBinder.getSimpleValueBinder().setVersion(true);
 			rootClass.setVersion( prop );
 
 			//If version is on a mapped superclass, update the mapping
@@ -1451,7 +1489,8 @@
 					ignoreNotFound, onDeleteCascade,
 					ToOneBinder.getTargetEntity( inferredData, mappings ),
 					propertyHolder,
-					inferredData, false, isIdentifierMapper, inSecondPass, mappings
+					inferredData, false, isIdentifierMapper,
+					inSecondPass, propertyBinder, mappings
 			);
 		}
 		else if ( property.isAnnotationPresent( OneToOne.class ) ) {
@@ -1489,7 +1528,13 @@
 					ignoreNotFound, onDeleteCascade,
 					ToOneBinder.getTargetEntity( inferredData, mappings ),
 					propertyHolder,
-					inferredData, ann.mappedBy(), trueOneToOne, isIdentifierMapper, inSecondPass, mappings
+					inferredData,
+					ann.mappedBy(),
+					trueOneToOne,
+					isIdentifierMapper,
+					inSecondPass,
+					propertyBinder,
+					mappings
 			);
 		}
 		else if ( property.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) {
@@ -1793,7 +1838,7 @@
 			isComponent = property.isAnnotationPresent( Embedded.class )
 					|| property.isAnnotationPresent( EmbeddedId.class )
 					|| returnedClass.isAnnotationPresent( Embeddable.class );
-			PropertyBinder propertyBinder;
+
 			if ( isComponent ) {
 				AccessType propertyAccessor = entityBinder.getPropertyAccessor( property );
 				propertyBinder = bindComponent(
@@ -1835,23 +1880,12 @@
 							mappings );
 				}
 
-				propertyBinder = new PropertyBinder();
-				propertyBinder.setName( inferredData.getPropertyName() );
-				propertyBinder.setReturnedClassName( inferredData.getTypeName() );
 				propertyBinder.setLazy( lazy );
-				propertyBinder.setAccessType( inferredData.getDefaultAccess() );
 				propertyBinder.setColumns( columns );
-				propertyBinder.setHolder( propertyHolder );
-				propertyBinder.setProperty( property );
-				propertyBinder.setReturnedClass( inferredData.getPropertyClass() );
-				propertyBinder.setMappings( mappings );
-				if ( isIdentifierMapper ) {
-					propertyBinder.setInsertable( false );
-					propertyBinder.setUpdatable( false );
-				}
-				propertyBinder.setDeclaringClass( inferredData.getDeclaringClass() );
-				propertyBinder.setId(isId);
-				propertyBinder.setInheritanceStatePerClass(inheritanceStatePerClass);
+//				if ( isIdentifierMapper ) {
+//					propertyBinder.setInsertable( false );
+//					propertyBinder.setUpdatable( false );
+//				}
 				propertyBinder.makePropertyValueAndBind();
 			}
 			if (isId) {
@@ -2105,6 +2139,7 @@
 		binder.setEmbedded( isComponentEmbedded );
 		binder.setHolder( propertyHolder );
 		binder.setId( isId );
+		binder.setEntityBinder( entityBinder );
 		binder.setInheritanceStatePerClass( inheritanceStatePerClass );
 		binder.setMappings( mappings );
 		binder.makePropertyAndBind();
@@ -2136,17 +2171,7 @@
 		 * Because it's a value type, there is no bidirectional association, hence second pass
 		 * ordering does not matter
 		 */
-		Component comp = new Component( propertyHolder.getPersistentClass() );
-		comp.setEmbedded( isComponentEmbedded );
-		//yuk
-		comp.setTable( propertyHolder.getTable() );
-		if ( !isIdentifierMapper ) {
-			comp.setComponentClassName( inferredData.getClassOrElementName() );
-		}
-		else {
-			comp.setComponentClassName( comp.getOwner().getClassName() );
-		}
-		comp.setNodeName( inferredData.getPropertyName() );
+		Component comp = createComponent( propertyHolder, inferredData, isComponentEmbedded, isIdentifierMapper );
 		String subpath = BinderHelper.getPath( propertyHolder, inferredData );
 		log.trace( "Binding component with path: {}", subpath );
 		PropertyHolder subHolder = PropertyHolderBuilder.buildPropertyHolder(
@@ -2202,6 +2227,22 @@
 		return comp;
 	}
 
+	public static Component createComponent(PropertyHolder propertyHolder, PropertyData inferredData, boolean isComponentEmbedded, boolean isIdentifierMapper) {
+		Component comp = new Component( propertyHolder.getPersistentClass() );
+		comp.setEmbedded( isComponentEmbedded );
+		//yuk
+		comp.setTable( propertyHolder.getTable() );
+		//FIXME shouldn't identifier mapper use getClassOrElementName? Need to be checked.
+		if ( isIdentifierMapper || ( isComponentEmbedded && inferredData.getPropertyName() == null ) ) {
+			comp.setComponentClassName( comp.getOwner().getClassName() );
+		}
+		else {
+			comp.setComponentClassName( inferredData.getClassOrElementName() );
+		}
+		comp.setNodeName( inferredData.getPropertyName() );
+		return comp;
+	}
+
 	private static void bindId(
 			String generatorType, String generatorName,
 			PropertyData inferredData, Ejb3Column[] columns, PropertyHolder propertyHolder,
@@ -2345,7 +2386,9 @@
 			String cascadeStrategy, Ejb3JoinColumn[] columns, boolean optional,
 			boolean ignoreNotFound, boolean cascadeOnDelete,
 			XClass targetEntity, PropertyHolder propertyHolder,
-			PropertyData inferredData, boolean unique, boolean isIdentifierMapper, boolean inSecondPass,
+			PropertyData inferredData, boolean unique,
+			boolean isIdentifierMapper, boolean inSecondPass,
+			PropertyBinder propertyBinder,
 			ExtendedMappings mappings
 	) {
 		//All FK columns should be in the same table
@@ -2399,24 +2442,26 @@
 			);
 		}
 		Ejb3Column.checkPropertyConsistency( columns, propertyHolder.getEntityName() + propertyName );
-		PropertyBinder binder = new PropertyBinder();
-		binder.setName( propertyName );
-		binder.setValue( value );
+		//PropertyBinder binder = new PropertyBinder();
+		propertyBinder.setName( propertyName );
+		propertyBinder.setValue( value );
 		//binder.setCascade(cascadeStrategy);
 		if ( isIdentifierMapper ) {
-			binder.setInsertable( false );
-			binder.setUpdatable( false );
+			propertyBinder.setInsertable( false );
+			propertyBinder.setUpdatable( false );
 		}
 		else {
-			binder.setInsertable( columns[0].isInsertable() );
-			binder.setUpdatable( columns[0].isUpdatable() );
+			propertyBinder.setInsertable( columns[0].isInsertable() );
+			propertyBinder.setUpdatable( columns[0].isUpdatable() );
 		}
-		binder.setAccessType( inferredData.getDefaultAccess() );
-		binder.setCascade( cascadeStrategy );
-		binder.setProperty( property );
-		Property prop = binder.makeProperty();
+		propertyBinder.setColumns( columns );
+		propertyBinder.setAccessType( inferredData.getDefaultAccess() );
+		propertyBinder.setCascade( cascadeStrategy );
+		propertyBinder.setProperty( property );
+		propertyBinder.setXToMany( true );
+		Property prop = propertyBinder.makePropertyAndBind();
 		//composite FK columns are in the same table so its OK
-		propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
+		//propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
 	}
 
 	protected static void defineFetchingStrategy(ToOne toOne, XProperty property) {
@@ -2476,7 +2521,10 @@
 			PropertyHolder propertyHolder,
 			PropertyData inferredData, String mappedBy,
 			boolean trueOneToOne,
-			boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings
+			boolean isIdentifierMapper,
+			boolean inSecondPass,
+			PropertyBinder propertyBinder,
+			ExtendedMappings mappings
 	) {
 		//column.getTable() => persistentClass.getTable()
 		final String propertyName = inferredData.getPropertyName();
@@ -2535,7 +2583,8 @@
 			bindManyToOne(
 					cascadeStrategy, joinColumns, optional, ignoreNotFound, cascadeOnDelete,
 					targetEntity,
-					propertyHolder, inferredData, true, isIdentifierMapper, inSecondPass, mappings
+					propertyHolder, inferredData, true, isIdentifierMapper, inSecondPass,
+					propertyBinder, mappings
 			);
 		}
 	}

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java	2010-01-25 16:23:59 UTC (rev 18618)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -119,7 +119,12 @@
 	private boolean ignoreIdAnnotations;
 	private boolean cacheLazyProperty;
 	private AccessType propertyAccessType = AccessType.DEFAULT;
+	private boolean wrapIdsInEmbeddedComponents;
 
+	public boolean wrapIdsInEmbeddedComponents() {
+		return wrapIdsInEmbeddedComponents;
+	}
+
 	/**
 	 * Use as a fake one for Collection of elements
 	 */
@@ -413,6 +418,11 @@
 		}
 	}
 
+	public void setWrapIdsInEmbeddedComponents(boolean wrapIdsInEmbeddedComponents) {
+		this.wrapIdsInEmbeddedComponents = wrapIdsInEmbeddedComponents;
+	}
+
+
 	private static class EntityTableObjectNameSource implements ObjectNameSource {
 		private final String explicitName;
 		private final String logicalName;

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java	2010-01-25 16:23:59 UTC (rev 18618)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -40,11 +40,14 @@
 import org.hibernate.annotations.common.reflection.XClass;
 import org.hibernate.annotations.common.reflection.XProperty;
 import org.hibernate.cfg.AccessType;
+import org.hibernate.cfg.AnnotationBinder;
 import org.hibernate.cfg.BinderHelper;
 import org.hibernate.cfg.Ejb3Column;
 import org.hibernate.cfg.ExtendedMappings;
 import org.hibernate.cfg.InheritanceState;
 import org.hibernate.cfg.PropertyHolder;
+import org.hibernate.cfg.PropertyPreloadedData;
+import org.hibernate.mapping.Component;
 import org.hibernate.mapping.KeyValue;
 import org.hibernate.mapping.Property;
 import org.hibernate.mapping.PropertyGeneration;
@@ -73,15 +76,21 @@
 	private XClass declaringClass;
 	private boolean declaringClassSet;
 	private boolean embedded;
+	private EntityBinder entityBinder;
+	private boolean isXToMany;
 
 	public void setEmbedded(boolean embedded) {
 		this.embedded = embedded;
 	}
 
+	public void setEntityBinder(EntityBinder entityBinder) {
+		this.entityBinder = entityBinder;
+	}
+
 	/*
-		 * property can be null
-		 * prefer propertyName to property.getName() since some are overloaded
-		 */
+			 * property can be null
+			 * prefer propertyName to property.getName() since some are overloaded
+			 */
 	private XProperty property;
 	private XClass returnedClass;
 	private boolean isId;
@@ -185,27 +194,45 @@
 		return bind( makePropertyAndValue() );
 	}
 
+	public void setXToMany(boolean xToMany) {
+		this.isXToMany = xToMany;
+	}
+
 	private Property bind(Property prop) {
 		if (isId) {
 			final RootClass rootClass = ( RootClass ) holder.getPersistentClass();
-			rootClass.setIdentifier( ( KeyValue ) getValue() );
-
-			if (embedded) {
-				rootClass.setEmbeddedIdentifier( true );
+			//if an xToMany, it as to be wrapped today.
+			//FIXME this pose a problem as the PK is the class instead of the associated class which is not really compliant with the spec
+			if ( isXToMany || entityBinder.wrapIdsInEmbeddedComponents() ) {
+				Component identifier = (Component) rootClass.getIdentifier();
+				if (identifier == null) {
+					identifier = AnnotationBinder.createComponent( holder, new PropertyPreloadedData(null, null, null), true, false );
+					rootClass.setIdentifier( identifier );
+					identifier.setNullValue( "undefined" );
+					rootClass.setEmbeddedIdentifier( true );
+				}
+				//FIXME is it good enough?
+				identifier.addProperty( prop );
 			}
 			else {
-				rootClass.setIdentifierProperty( prop );
-				final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(
-						declaringClass,
-						inheritanceStatePerClass,
-						mappings
-				);
-				if (superclass != null) {
-					superclass.setDeclaredIdentifierProperty(prop);
+				rootClass.setIdentifier( ( KeyValue ) getValue() );
+				if (embedded) {
+					rootClass.setEmbeddedIdentifier( true );
 				}
 				else {
-					//we know the property is on the actual entity
-					rootClass.setDeclaredIdentifierProperty( prop );
+					rootClass.setIdentifierProperty( prop );
+					final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(
+							declaringClass,
+							inheritanceStatePerClass,
+							mappings
+					);
+					if (superclass != null) {
+						superclass.setDeclaredIdentifierProperty(prop);
+					}
+					else {
+						//we know the property is on the actual entity
+						rootClass.setDeclaredIdentifierProperty( prop );
+					}
 				}
 			}
 		}

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/Version.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/Version.java	2010-01-25 16:23:59 UTC (rev 18618)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/Version.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -1,4 +1,4 @@
-// $Id:$
+// $Id$
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
@@ -24,6 +24,8 @@
  */
 package org.hibernate.cfg.annotations;
 
+import java.util.Date;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -34,7 +36,7 @@
 	private static Logger log = LoggerFactory.getLogger( Version.class );
 
 	public static String getVersionString() {
-		return "[WORKING]";
+		return "[WORKING]-1";
 	}
 
 	static {

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/Dependent.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/Dependent.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/Dependent.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -0,0 +1,25 @@
+package org.hibernate.test.annotations.derivedidentities.e1.c;
+
+import java.io.Serializable;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class Dependent implements Serializable {
+
+	@Id
+	String name;
+
+
+	@Id
+	//@JoinColumn(name = "FK")
+	// id attribute mapped by join column default
+	@ManyToOne
+	Employee emp;
+
+}

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/DerivedIdentitySimpleParentEmbeddedDepTest.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -0,0 +1,46 @@
+package org.hibernate.test.annotations.derivedidentities.e1.c;
+
+import org.hibernate.Session;
+import org.hibernate.test.annotations.TestCase;
+import org.hibernate.test.util.SchemaUtil;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class DerivedIdentitySimpleParentEmbeddedDepTest extends TestCase {
+
+	public void testManyToOne() throws Exception {
+		assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", getCfg() ) );
+		assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", getCfg() ) );
+		Employee e = new Employee();
+		e.empId = 1;
+		e.empName = "Emmanuel";
+		Session s = openSession(  );
+		s.getTransaction().begin();
+		s.persist( e );
+		Dependent d = new Dependent();
+		d.emp = e;
+		d.name = "Doggy";
+		s.persist( d );
+		s.flush();
+		s.clear();
+		d = getDerivedClassById( e, s, Dependent.class, d.name );
+		assertEquals( e.empId, d.emp.empId );
+		s.getTransaction().rollback();
+		s.close();
+	}
+
+	private <T> T getDerivedClassById(Employee e, Session s, Class<T> clazz, String name) {
+		return ( T )
+				s.createQuery( "from " + clazz.getName() + " d where d.name = :name and d.emp.empId = :empId")
+					.setParameter( "empId", e.empId ).setParameter( "name", name ).uniqueResult();
+	}
+
+	@Override
+	protected Class<?>[] getAnnotatedClasses() {
+		return new Class<?>[] {
+				Dependent.class,
+				Employee.class
+		};
+	}
+}

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/Employee.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/Employee.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/c/Employee.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -0,0 +1,14 @@
+package org.hibernate.test.annotations.derivedidentities.e1.c;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class Employee {
+	@Id
+	long empId;
+	String empName;
+}

Copied: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java (from rev 18592, core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/DerivedIdentitySimpleParentSimpleDepTest.java)
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -0,0 +1,78 @@
+package org.hibernate.test.annotations.derivedidentities.e4.a;
+
+import java.util.Date;
+
+import org.hibernate.Session;
+import org.hibernate.test.annotations.TestCase;
+import org.hibernate.test.util.SchemaUtil;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class DerivedIdentitySimpleParentSimpleDepTest extends TestCase {
+
+	public void testOneToOneExplicitJoinColumn() throws Exception {
+		assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", getCfg() ) );
+		assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", getCfg() ) );
+		Person e = new Person();
+		e.ssn = "aaa";
+		Session s = openSession(  );
+		s.getTransaction().begin();
+		s.persist( e );
+		MedicalHistory d = new MedicalHistory();
+		d.patient = e;
+		s.persist( d );
+		s.flush();
+		s.clear();
+		final Class<MedicalHistory> clazz = MedicalHistory.class;
+		d = getDerivedClassById( e, s, clazz );
+		assertEquals( e.ssn, d.patient.ssn );
+		d.lastupdate = new Date();
+		s.flush();
+		s.clear();
+		d = getDerivedClassById( e, s, clazz );
+		assertNotNull( d.lastupdate );
+		s.getTransaction().rollback();
+		s.close();
+	}
+
+	private <T> T getDerivedClassById(Person e, Session s, Class<T> clazz) {
+		return ( T )
+				s.createQuery( "from " + clazz.getName() + " mh where mh.patient.ssn = :ssn")
+					.setParameter( "ssn", e.ssn ).uniqueResult();
+	}
+
+	public void testManyToOneExplicitJoinColumn() throws Exception {
+		assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "patient_ssn", getCfg() ) );
+		assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", getCfg() ) );
+		Person e = new Person();
+		e.ssn = "aaa";
+		Session s = openSession(  );
+		s.getTransaction().begin();
+		s.persist( e );
+		FinancialHistory d = new FinancialHistory();
+		d.patient = e;
+		s.persist( d );
+		s.flush();
+		s.clear();
+		d = getDerivedClassById(e, s, FinancialHistory.class);
+		assertEquals( e.ssn, d.patient.ssn );
+		d.lastupdate = new Date();
+		s.flush();
+		s.clear();
+		d = getDerivedClassById(e, s, FinancialHistory.class);
+		assertNotNull( d.lastupdate );
+		s.getTransaction().rollback();
+		s.close();
+	}
+
+	@Override
+	protected Class<?>[] getAnnotatedClasses() {
+		return new Class<?>[] {
+				MedicalHistory.class,
+				Simple.class,
+				Person.class,
+				FinancialHistory.class
+		};
+	}
+}
\ No newline at end of file

Copied: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/FinancialHistory.java (from rev 18592, core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/FinancialHistory.java)
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/FinancialHistory.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/FinancialHistory.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -0,0 +1,28 @@
+package org.hibernate.test.annotations.derivedidentities.e4.a;
+
+import java.io.Serializable;
+import java.util.Date;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapsId;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class FinancialHistory implements Serializable {
+	
+	@Temporal(TemporalType.DATE)
+	Date lastupdate;
+
+	@Id
+	//@JoinColumn(name = "FK")
+	@ManyToOne
+	Person patient;
+
+}
\ No newline at end of file

Copied: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/MedicalHistory.java (from rev 18592, 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/a/MedicalHistory.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/MedicalHistory.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -0,0 +1,27 @@
+package org.hibernate.test.annotations.derivedidentities.e4.a;
+
+import java.io.Serializable;
+import java.util.Date;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.MapsId;
+import javax.persistence.OneToOne;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class MedicalHistory implements Serializable {
+
+	@Temporal(TemporalType.DATE)
+	Date lastupdate;
+
+	@Id
+	@JoinColumn(name = "FK")
+	@OneToOne
+	Person patient;
+}
\ No newline at end of file

Copied: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java (from rev 18592, 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/a/Person.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -0,0 +1,14 @@
+package org.hibernate.test.annotations.derivedidentities.e4.a;
+
+import java.io.Serializable;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class Person {
+	@Id
+	String ssn;
+}
\ No newline at end of file

Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Simple.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Simple.java	                        (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Simple.java	2010-01-25 17:19:05 UTC (rev 18619)
@@ -0,0 +1,17 @@
+package org.hibernate.test.annotations.derivedidentities.e4.a;
+
+import java.io.Serializable;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class Simple
+		implements Serializable {
+	@Id
+	String ssn;
+	@Id
+	String name;
+}



More information about the hibernate-commits mailing list