Author: epbernard
Date: 2010-02-04 12:54:05 -0500 (Thu, 04 Feb 2010)
New Revision: 18692
Modified:
core/trunk/annotations/src/main/java/org/hibernate/cfg/AbstractPropertyHolder.java
core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java
core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java
core/trunk/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java
core/trunk/annotations/src/main/java/org/hibernate/cfg/ColumnsBuilder.java
core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java
core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolder.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DependentId.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/Employee.java
core/trunk/core/src/main/java/org/hibernate/id/ForeignGenerator.java
core/trunk/core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java
core/trunk/core/src/main/java/org/hibernate/type/EntityType.java
Log:
HHH-4848 partial implementation of @IdClass support in derivedidentity (example 1 case a
of the spec)
Modified:
core/trunk/annotations/src/main/java/org/hibernate/cfg/AbstractPropertyHolder.java
===================================================================
---
core/trunk/annotations/src/main/java/org/hibernate/cfg/AbstractPropertyHolder.java 2010-02-04
17:27:20 UTC (rev 18691)
+++
core/trunk/annotations/src/main/java/org/hibernate/cfg/AbstractPropertyHolder.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -55,6 +55,7 @@
private Map<String, JoinTable> currentPropertyJoinTableOverride;
private String path;
private ExtendedMappings mappings;
+ private Boolean isInIdClass;
public AbstractPropertyHolder(
@@ -66,6 +67,15 @@
buildHierarchyColumnOverride( clazzToProcess );
}
+
+ public boolean isInIdClass() {
+ return isInIdClass != null ? isInIdClass : parent != null ? parent.isInIdClass() :
false;
+ }
+
+ public void setInIdClass(Boolean isInIdClass) {
+ this.isInIdClass = isInIdClass;
+ }
+
public String getPath() {
return path;
}
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-04
17:27:20 UTC (rev 18691)
+++
core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -701,6 +701,7 @@
HashMap<String, IdGenerator> localGenerators = new HashMap<String,
IdGenerator>();
boolean ignoreIdAnnotations = entityBinder.isIgnoreIdAnnotations();
entityBinder.setIgnoreIdAnnotations( true );
+ propertyHolder.setInIdClass( true );
bindId(
generatorType,
generator,
@@ -716,6 +717,7 @@
mappings,
inheritanceStatePerClass
);
+ propertyHolder.setInIdClass( null );
inferredData = new PropertyPreloadedData(
propertyAccessor, "_identifierMapper", compositeClass
);
@@ -728,7 +730,9 @@
entityBinder,
true,
true,
- false, mappings, inheritanceStatePerClass
+ false,
+ mappings,
+ inheritanceStatePerClass
);
entityBinder.setIgnoreIdAnnotations( ignoreIdAnnotations );
persistentClass.setIdentifierMapper( mapper );
@@ -1164,7 +1168,7 @@
* strategy is used
* @param propertyContainer Metadata about a class and its properties
* @param mappings Mapping meta data
- * @return the number of id properties found while iterating the elements of {@code
annoatedClass} using
+ * @return the number of id properties found while iterating the elements of {@code
annotatedClass} using
* the determined access strategy, {@code false} otherwise.
*/
static int addElementsOfClass(
@@ -1206,6 +1210,9 @@
final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent(
EmbeddedId.class ) ) {
annElts.add( 0, propertyAnnotatedElement );
+ if ( element.isAnnotationPresent( ManyToOne.class ) || element.isAnnotationPresent(
OneToOne.class ) ) {
+ mappings.addToOneAndIdProperty( entity, propertyAnnotatedElement );
+ }
idPropertyCounter++;
}
else {
@@ -1713,15 +1720,15 @@
//FIXME do the overrideColumnFromMapsIdProperty here and force the idclass type to
look like an @embedded
//Overrides from @MapsId if needed
boolean isOverridden = false;
- if ( isId || propertyHolder.isOrWithinEmbeddedId() ) {
+ if ( isId || propertyHolder.isOrWithinEmbeddedId() || propertyHolder.isInIdClass() )
{
Ejb3Column[] oldColumns = columns;
- columns = columnsBuilder.overrideColumnFromMapsIdProperty(isId);
+ columns = columnsBuilder.overrideColumnFromMapperOrMapsIdProperty(isId);
isOverridden = oldColumns != columns;
}
if ( isComponent ) {
String referencedEntityName = null;
if (isOverridden) {
- final PropertyData mapsIdProperty = BinderHelper.getPropertyAnnotatedWithMapsId(
+ final PropertyData mapsIdProperty =
BinderHelper.getPropertyOverriddenByMapperOrMapsId(
isId, propertyHolder, property.getName(), mappings
);
referencedEntityName = mapsIdProperty.getClassOrElementName();
@@ -1761,7 +1768,7 @@
propertyBinder.setLazy( lazy );
propertyBinder.setColumns( columns );
if (isOverridden) {
- final PropertyData mapsIdProperty = BinderHelper.getPropertyAnnotatedWithMapsId(
+ final PropertyData mapsIdProperty =
BinderHelper.getPropertyOverriddenByMapperOrMapsId(
isId, propertyHolder, property.getName(), mappings
);
propertyBinder.setReferencedEntityName( mapsIdProperty.getClassOrElementName() );
@@ -1771,7 +1778,7 @@
}
if (isOverridden) {
- final PropertyData mapsIdProperty = BinderHelper.getPropertyAnnotatedWithMapsId(
+ final PropertyData mapsIdProperty =
BinderHelper.getPropertyOverriddenByMapperOrMapsId(
isId, propertyHolder, property.getName(), mappings
);
HashMap<String, IdGenerator> localGenerators = (HashMap<String,
IdGenerator>) classGenerators.clone();
@@ -2021,7 +2028,8 @@
}
public static Component fillComponent(
- PropertyHolder propertyHolder, PropertyData inferredData, PropertyData
baseInferredData,
+ PropertyHolder propertyHolder, PropertyData inferredData,
+ PropertyData baseInferredData, //base inferred data correspond to the entity
reproducing inferredData's properties (ie IdClass)
AccessType propertyAccessor, boolean isNullable, EntityBinder entityBinder,
boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass,
ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
@@ -2045,14 +2053,17 @@
XClass returnedClassOrElement = inferredData.getClassOrElement();
List<PropertyData> baseClassElements = null;
+ Map<String, PropertyData> orderedBaseClassElements = new HashMap<String,
PropertyData>();
XClass baseReturnedClassOrElement;
- if(baseInferredData != null)
- {
+ if(baseInferredData != null) {
baseClassElements = new ArrayList<PropertyData>();
baseReturnedClassOrElement = baseInferredData.getClassOrElement();
bindTypeDefs(baseReturnedClassOrElement, mappings);
PropertyContainer propContainer = new PropertyContainer(
baseReturnedClassOrElement, entityXClass );
addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );
+ for (PropertyData element : baseClassElements) {
+ orderedBaseClassElements.put( element.getPropertyName(), element );
+ }
}
//embeddable elements can have type defs
@@ -2069,9 +2080,24 @@
superClass = superClass.getSuperclass();
}
if ( baseClassElements != null ) {
- if ( !hasIdClassAnnotations( entityXClass ) ) {
+ //useful to avoid breaking pre JPA 2 mappings
+ if ( !hasAnnotationsOnIdClass( entityXClass ) ) {
for ( int i = 0; i < classElements.size(); i++ ) {
- classElements.set( i, baseClassElements.get( i ) ); //this works since they are in
the same order
+ final PropertyData idClassPropertyData = classElements.get( i );
+ final PropertyData entityPropertyData = orderedBaseClassElements.get(
idClassPropertyData.getPropertyName() );
+ 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
+ }
+ }
+ else {
+ classElements.set( i, entityPropertyData ); //this works since they are in the
same order
+ }
}
}
}
@@ -2087,10 +2113,9 @@
XProperty property = propertyAnnotatedElement.getProperty();
if(property.isAnnotationPresent(GeneratedValue.class) &&
- property.isAnnotationPresent(Id.class))
- {
+ property.isAnnotationPresent(Id.class) ) {
//clone classGenerator and override with local values
- HashMap<String, IdGenerator> localGenerators = (HashMap<String,
IdGenerator>) new HashMap<String, IdGenerator>();
+ HashMap<String, IdGenerator> localGenerators = new HashMap<String,
IdGenerator>();
localGenerators.putAll( buildLocalGenerators( property, mappings ) );
GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
@@ -2647,10 +2672,10 @@
return inheritanceStatePerClass;
}
- private static boolean hasIdClassAnnotations(XClass idClass)
+ private static boolean hasAnnotationsOnIdClass(XClass idClass)
{
- if(idClass.getAnnotation(Embeddable.class) != null)
- return true;
+// if(idClass.getAnnotation(Embeddable.class) != null)
+// return true;
List<XProperty> properties = idClass.getDeclaredProperties( XClass.ACCESS_FIELD
);
for ( XProperty property : properties ) {
Modified:
core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java
===================================================================
---
core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java 2010-02-04
17:27:20 UTC (rev 18691)
+++
core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -65,7 +65,6 @@
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.MappingException;
-import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.annotations.AnyMetaDef;
import org.hibernate.annotations.Cache;
@@ -158,6 +157,7 @@
private boolean isDefaultProcessed = false;
private boolean isValidatorNotPresentLogged;
private Map<XClass,Map<String,PropertyData>> propertiesAnnotatedWithMapsId;
+ private Map<XClass,Map<String,PropertyData>>
propertiesAnnotatedWithIdAndToOne;
public AnnotationConfiguration() {
super();
@@ -297,6 +297,7 @@
setEntityResolver( new EJB3DTDEntityResolver() );
anyMetaDefs = new HashMap<String, AnyMetaDef>();
propertiesAnnotatedWithMapsId = new HashMap<XClass,
Map<String,PropertyData>>();
+ propertiesAnnotatedWithIdAndToOne = new HashMap<XClass,
Map<String,PropertyData>>();
reflectionManager = new JavaReflectionManager();
( ( MetadataProviderInjector ) reflectionManager ).setMetadataProvider( new
JPAMetadataProvider() );
@@ -1293,6 +1294,20 @@
map.put( property.getProperty().getAnnotation( MapsId.class ).value(), property );
}
+ public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String
propertyName) {
+ final Map<String, PropertyData> map = propertiesAnnotatedWithIdAndToOne.get(
entityType );
+ return map == null ? null : map.get( propertyName );
+ }
+
+ public void addToOneAndIdProperty(XClass entityType, PropertyData property) {
+ Map<String, PropertyData> map = propertiesAnnotatedWithIdAndToOne.get(
entityType );
+ if (map == null) {
+ map = new HashMap<String, PropertyData>();
+ propertiesAnnotatedWithIdAndToOne.put( entityType, map );
+ }
+ map.put( property.getPropertyName(), property );
+ }
+
private Boolean useNewGeneratorMappings;
@SuppressWarnings({ "UnnecessaryUnboxing" })
Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java 2010-02-04
17:27:20 UTC (rev 18691)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -652,7 +652,7 @@
return StringHelper.qualify( holder.getPath(), property.getPropertyName() );
}
- static PropertyData getPropertyAnnotatedWithMapsId(boolean isId, PropertyHolder
propertyHolder, String propertyName, ExtendedMappings mappings) {
+ static PropertyData getPropertyOverriddenByMapperOrMapsId(boolean isId, PropertyHolder
propertyHolder, String propertyName, ExtendedMappings mappings) {
final XClass persistentXClass;
try {
persistentXClass = mappings.getReflectionManager()
@@ -661,8 +661,12 @@
catch ( ClassNotFoundException e ) {
throw new AssertionFailure( "PersistentClass name cannot be converted into a
Class", e);
}
- String propertyPath = isId ? "" : propertyName;
- final PropertyData annotatedWithMapsId = mappings.getPropertyAnnotatedWithMapsId(
persistentXClass, propertyPath );
- return annotatedWithMapsId;
+ if ( propertyHolder.isInIdClass() ) {
+ return mappings.getPropertyAnnotatedWithIdAndToOne( persistentXClass, propertyName );
+ }
+ else {
+ String propertyPath = isId ? "" : propertyName;
+ return mappings.getPropertyAnnotatedWithMapsId( persistentXClass, propertyPath );
+ }
}
}
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-04
17:27:20 UTC (rev 18691)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/ColumnsBuilder.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -11,12 +11,10 @@
import javax.persistence.OneToOne;
import org.hibernate.AnnotationException;
-import org.hibernate.AssertionFailure;
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.Formula;
import org.hibernate.annotations.JoinColumnsOrFormulas;
-import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.cfg.annotations.EntityBinder;
import org.hibernate.cfg.annotations.Nullability;
@@ -183,15 +181,13 @@
return joinColumns;
}
- Ejb3Column[] overrideColumnFromMapsIdProperty(boolean isId) {
+ Ejb3Column[] overrideColumnFromMapperOrMapsIdProperty(boolean isId) {
Ejb3Column[] result = columns;
- final PropertyData annotatedWithMapsId = BinderHelper.getPropertyAnnotatedWithMapsId(
isId, propertyHolder, property.getName(), mappings );
+ final PropertyData annotatedWithMapsId =
BinderHelper.getPropertyOverriddenByMapperOrMapsId( isId, propertyHolder,
property.getName(), mappings );
if ( annotatedWithMapsId != null ) {
result = buildExplicitJoinColumns( annotatedWithMapsId.getProperty(),
annotatedWithMapsId );
if (result == null) {
result = buildDefaultJoinColumnsForXToOne( annotatedWithMapsId.getProperty(),
annotatedWithMapsId);
-// throw new UnsupportedOperationException( "Implicit @JoinColumn is not
supported on @MapsId properties: "
-// + annotatedWithMapsId.getDeclaringClass() + " " +
annotatedWithMapsId.getPropertyName() );
}
}
return result;
Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java
===================================================================
---
core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java 2010-02-04
17:27:20 UTC (rev 18691)
+++
core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -188,4 +188,12 @@
* @return True if the new generators should be used, false otherwise.
*/
public boolean useNewGeneratorMappings();
+
+ /**
+ * Return the property annotated with @ToOne and @Id if any.
+ * Null otherwise
+ */
+ public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String
propertyName);
+
+ void addToOneAndIdProperty(XClass entity, PropertyData property);
}
\ No newline at end of file
Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolder.java 2010-02-04
17:27:20 UTC (rev 18691)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolder.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -89,4 +89,8 @@
String getEntityName();
Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation);
+
+ boolean isInIdClass();
+
+ void setInIdClass(Boolean isInIdClass);
}
Modified:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DependentId.java
===================================================================
---
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DependentId.java 2010-02-04
17:27:20 UTC (rev 18691)
+++
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DependentId.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -7,5 +7,5 @@
*/
public class DependentId implements Serializable {
String name;
- long empPK; // corresponds to PK type of Employee
+ long emp; // corresponds to PK type of Employee
}
\ No newline at end of file
Modified:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java
===================================================================
---
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java 2010-02-04
17:27:20 UTC (rev 18691)
+++
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/DerivedIdentitySimpleParentIdClassDepTest.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -1,6 +1,7 @@
package org.hibernate.test.annotations.derivedidentities.e1.a;
import org.hibernate.Session;
+import org.hibernate.junit.FailureExpected;
import org.hibernate.test.annotations.TestCase;
import org.hibernate.test.util.SchemaUtil;
@@ -10,36 +11,40 @@
public class
DerivedIdentitySimpleParentIdClassDepTest extends TestCase {
+ @FailureExpected( jiraKey = "HHH-4848" )
public void testManyToOne() throws Exception {
-// assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK",
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";
-// d.emp = e;
-// s.persist( d );
-// s.flush();
-// s.clear();
-// DependentId dId = new DependentId();
-// dId.name = d.name;
-// dId.empPK = d.emp.empId;
-// d = (Dependent) s.get( Dependent.class, dId );
-// assertEquals( e.empId, d.emp.empId );
-// s.getTransaction().rollback();
-// s.close();
+ assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId",
getCfg() ) );
+ assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "emp",
getCfg() ) );
+ Employee e = new Employee();
+ e.empId = 1;
+ e.empName = "Emmanuel";
+ e.nickname = "Manu";
+ Session s = openSession( );
+ s.getTransaction().begin();
+ s.persist( e );
+ Dependent d = new Dependent();
+ d.emp = e;
+ d.name = "Doggy";
+ d.emp = e;
+ s.persist( d );
+ s.flush();
+ s.clear();
+ DependentId dId = new DependentId();
+ dId.name = d.name;
+ dId.emp = d.emp.empId;
+ d = (Dependent) s.get( Dependent.class, dId );
+ assertEquals( e.empId, d.emp.empId );
+ assertEquals( e.empName, d.emp.empName );
+ assertEquals( e.nickname, d.emp.nickname );
+ s.getTransaction().rollback();
+ s.close();
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
- //Dependent.class,
- //Employee.class
+ Dependent.class,
+ Employee.class
};
}
}
\ No newline at end of file
Modified:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/Employee.java
===================================================================
---
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/Employee.java 2010-02-04
17:27:20 UTC (rev 18691)
+++
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/a/Employee.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -11,4 +11,6 @@
@Id
long empId;
String empName;
+
+ String nickname;
}
\ No newline at end of file
Modified: core/trunk/core/src/main/java/org/hibernate/id/ForeignGenerator.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/id/ForeignGenerator.java 2010-02-04
17:27:20 UTC (rev 18691)
+++ core/trunk/core/src/main/java/org/hibernate/id/ForeignGenerator.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -33,6 +33,7 @@
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.ForeignKeys;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
@@ -95,19 +96,27 @@
public Serializable generate(SessionImplementor sessionImplementor, Object object) {
Session session = ( Session ) sessionImplementor;
- Object associatedObject = sessionImplementor.getFactory()
- .getClassMetadata( entityName )
+ final ClassMetadata classMetadata = sessionImplementor.getFactory()
+ .getClassMetadata( entityName );
+ Object associatedObject = classMetadata
.getPropertyValue( object, propertyName, session.getEntityMode() );
if ( associatedObject == null ) {
throw new IdentifierGenerationException(
"attempted to assign id from null one-to-one property [" + getRole() +
"]"
);
}
-
- EntityType type = (EntityType) sessionImplementor.getFactory()
- .getClassMetadata( entityName )
- .getPropertyType( propertyName );
+ final Type uncheckedType = classMetadata
+ .getPropertyType( propertyName );
+ EntityType type;
+ if (uncheckedType instanceof EntityType) {
+ type = (EntityType) uncheckedType;
+ }
+ else {
+ //try identifier mapper
+ type = (EntityType) classMetadata.getPropertyType( "_identifierMapper." +
propertyName );
+ }
+
Serializable id;
try {
id = ForeignKeys.getEntityIdentifierIfNotUnsaved(
Modified:
core/trunk/core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java 2010-02-04
17:27:20 UTC (rev 18691)
+++
core/trunk/core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java 2010-02-04
17:54:05 UTC (rev 18692)
@@ -30,6 +30,8 @@
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
+import org.hibernate.PropertyAccessException;
+import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.VersionProperty;
import org.hibernate.tuple.StandardProperty;
@@ -45,6 +47,8 @@
import org.hibernate.proxy.ProxyFactory;
import org.hibernate.type.AbstractComponentType;
import org.hibernate.type.ComponentType;
+import org.hibernate.type.EntityType;
+import org.hibernate.type.Type;
/**
@@ -70,6 +74,9 @@
private final ProxyFactory proxyFactory;
private final AbstractComponentType identifierMapperType;
+ public Type getIdentifierMapperType() {
+ return identifierMapperType;
+ }
/**
* Build an appropriate Getter for the given property.
@@ -192,13 +199,27 @@
else {
ComponentType copier = (ComponentType)
entityMetamodel.getIdentifierProperty().getType();
id = copier.instantiate( getEntityMode() );
- copier.setPropertyValues( id, identifierMapperType.getPropertyValues( entity,
getEntityMode() ), getEntityMode() );
+ final Object[] propertyValues = identifierMapperType.getPropertyValues( entity,
getEntityMode() );
+ Type[] subTypes = identifierMapperType.getSubtypes();
+ Type[] copierSubTypes = copier.getSubtypes();
+ final int length = subTypes.length;
+ for ( int i = 0 ; i < length; i++ ) {
+ //JPA 2 in @IdClass points to the pk of the entity
+ if ( subTypes[i].isAssociationType() && !
copierSubTypes[i].isAssociationType()) {
+ final String associatedEntityName = ( ( EntityType ) subTypes[i]
).getAssociatedEntityName();
+ final EntityPersister entityPersister = getFactory().getEntityPersister(
+ associatedEntityName
+ );
+ propertyValues[i] = entityPersister.getIdentifier( propertyValues[i],
getEntityMode() );
+ }
+ }
+ copier.setPropertyValues( id, propertyValues, getEntityMode() );
}
}
else {
- id = idGetter.get( entity );
- }
- }
+ id = idGetter.get( entity );
+ }
+ }
try {
return (Serializable) id;
@@ -229,7 +250,18 @@
else if ( identifierMapperType != null ) {
ComponentType extractor = (ComponentType)
entityMetamodel.getIdentifierProperty().getType();
ComponentType copier = (ComponentType) identifierMapperType;
- copier.setPropertyValues( entity, extractor.getPropertyValues( id, getEntityMode() ),
getEntityMode() );
+ final Object[] propertyValues = extractor.getPropertyValues( id, getEntityMode() );
+ Type[] subTypes = identifierMapperType.getSubtypes();
+ Type[] copierSubTypes = copier.getSubtypes();
+ final int length = subTypes.length;
+ for ( int i = 0 ; i < length; i++ ) {
+ //JPA 2 in @IdClass points to the pk of the entity
+ if ( subTypes[i].isAssociationType() && !
copierSubTypes[i].isAssociationType() ) {
+ final String associatedEntityName = ( ( EntityType ) subTypes[i]
).getAssociatedEntityName();
+ //FIXME find the entity for the given id (propertyValue[i])
+ }
+ }
+ copier.setPropertyValues( entity, propertyValues, getEntityMode() );
}
}
@@ -299,18 +331,27 @@
}
public Object getPropertyValue(Object entity, String propertyPath) throws
HibernateException {
- final int loc = propertyPath.indexOf('.');
- final String basePropertyName = loc > 0
+ int loc = propertyPath.indexOf('.');
+ String basePropertyName = loc > 0
? propertyPath.substring( 0, loc )
: propertyPath;
- final int index = entityMetamodel.getPropertyIndex( basePropertyName );
- final Object baseValue = getPropertyValue( entity, index );
+ //final int index = entityMetamodel.getPropertyIndexOrNull( basePropertyName );
+ Integer index = entityMetamodel.getPropertyIndexOrNull( basePropertyName );
+ if (index == null) {
+ propertyPath = "_identifierMapper." + propertyPath;
+ loc = propertyPath.indexOf('.');
+ basePropertyName = loc > 0
+ ? propertyPath.substring( 0, loc )
+ : propertyPath;
+ }
+ index = entityMetamodel.getPropertyIndexOrNull( basePropertyName );
+ final Object baseValue = getPropertyValue( entity, index.intValue() );
if ( loc > 0 ) {
if ( baseValue == null ) {
return null;
}
return getComponentValue(
- (ComponentType) entityMetamodel.getPropertyTypes()[index],
+ (ComponentType) entityMetamodel.getPropertyTypes()[index.intValue()],
baseValue,
propertyPath.substring(loc+1)
);
Modified: core/trunk/core/src/main/java/org/hibernate/type/EntityType.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/type/EntityType.java 2010-02-04 17:27:20
UTC (rev 18691)
+++ core/trunk/core/src/main/java/org/hibernate/type/EntityType.java 2010-02-04 17:54:05
UTC (rev 18692)
@@ -307,7 +307,13 @@
id = ( (HibernateProxy) x ).getHibernateLazyInitializer().getIdentifier();
}
else {
- id = persister.getIdentifier(x, entityMode);
+ final Class mappedClass = persister.getMappedClass( entityMode );
+ if ( mappedClass.isAssignableFrom( x.getClass() ) ) {
+ id = persister.getIdentifier(x, entityMode);
+ }
+ else {
+ id = (Serializable) x;
+ }
}
return persister.getIdentifierType().getHashCode(id, entityMode, factory);
}
@@ -321,13 +327,20 @@
return super.isEqual(x, y, entityMode);
}
+ final Class mappedClass = persister.getMappedClass( entityMode );
Serializable xid;
if (x instanceof HibernateProxy) {
xid = ( (HibernateProxy) x ).getHibernateLazyInitializer()
.getIdentifier();
}
else {
- xid = persister.getIdentifier(x, entityMode);
+ if ( mappedClass.isAssignableFrom( x.getClass() ) ) {
+ xid = persister.getIdentifier(x, entityMode);
+ }
+ else {
+ //JPA 2 case where @IdClass contains the id and not the associated entity
+ xid = (Serializable) x;
+ }
}
Serializable yid;
@@ -336,7 +349,13 @@
.getIdentifier();
}
else {
- yid = persister.getIdentifier(y, entityMode);
+ if ( mappedClass.isAssignableFrom( y.getClass() ) ) {
+ yid = persister.getIdentifier(x, entityMode);
+ }
+ else {
+ //JPA 2 case where @IdClass contains the id and not the associated entity
+ yid = (Serializable) y;
+ }
}
return persister.getIdentifierType()