HHH-4529 Add support for id copy when @MapsId is used.

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18633 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Emmanuel Bernard 2010-01-26 17:15:37 +00:00
parent fc20582ede
commit 7c72886f6e
11 changed files with 147 additions and 155 deletions

View File

@ -967,127 +967,6 @@ public final class
return true;
}
// /*
// * Get the annotated elements, guessing the access type from @Id or @EmbeddedId presence.
// * Change EntityBinder by side effect
// */
// private static InheritanceState.ElementsToProcess getElementsToProcess(
// PersistentClass persistentClass, XClass clazzToProcess,
// Map<XClass, InheritanceState> inheritanceStatePerClass,
// EntityBinder entityBinder, ExtendedMappings mappings
// ) {
// InheritanceState inheritanceState = inheritanceStatePerClass.get( clazzToProcess );
// assert !inheritanceState.isEmbeddableSuperclass();
//
//
// List<XClass> classesToProcess = getMappedSuperclassesTillNextEntityOrdered(
// persistentClass, clazzToProcess, inheritanceStatePerClass, mappings
// );
//
// AccessType accessType = determineDefaultAccessType( clazzToProcess, inheritanceStatePerClass );
//
// List<PropertyData> elements = new ArrayList<PropertyData>();
// int deep = classesToProcess.size();
// int idPropertyCount = 0;
//
// for ( int index = 0; index < deep; index++ ) {
// PropertyContainer propertyContainer = new PropertyContainer( classesToProcess.get( index ), clazzToProcess );
// int currentIdPropertyCount = addElementsOfClass( elements, accessType, propertyContainer, mappings );
// idPropertyCount += currentIdPropertyCount;
// }
//
// entityBinder.setPropertyAccessType( accessType );
//
// if ( idPropertyCount == 0 && !inheritanceState.hasParents() ) {
// throw new AnnotationException( "No identifier specified for entity: " + clazzToProcess.getName() );
// }
//
// return new InheritanceState.ElementsToProcess( elements, idPropertyCount);
// }
// private static AccessType determineDefaultAccessType(XClass annotatedClass, Map<XClass, InheritanceState> inheritanceStatePerClass) {
// XClass xclass = annotatedClass;
// while ( xclass != null && !Object.class.getName().equals( xclass.getName() ) ) {
// if ( xclass.isAnnotationPresent( Entity.class ) || xclass.isAnnotationPresent( MappedSuperclass.class ) ) {
// for ( XProperty prop : xclass.getDeclaredProperties( AccessType.PROPERTY.getType() ) ) {
// if ( prop.isAnnotationPresent( Id.class ) || prop.isAnnotationPresent( EmbeddedId.class ) ) {
// return AccessType.PROPERTY;
// }
// }
// for ( XProperty prop : xclass.getDeclaredProperties( AccessType.FIELD.getType() ) ) {
// if ( prop.isAnnotationPresent( Id.class ) || prop.isAnnotationPresent( EmbeddedId.class ) ) {
// return AccessType.FIELD;
// }
// }
// }
// xclass = xclass.getSuperclass();
// }
// throw new AnnotationException( "No identifier specified for entity: " + annotatedClass.getName() );
// }
//
// private static List<XClass> getMappedSuperclassesTillNextEntityOrdered(
// PersistentClass persistentClass, XClass annotatedClass,
// Map<XClass, InheritanceState> inheritanceStatePerClass,
// ExtendedMappings mappings
// ) {
//
// //ordered to allow proper messages on properties subclassing
// List<XClass> classesToProcess = new ArrayList<XClass>();
// XClass currentClassInHierarchy = annotatedClass;
// InheritanceState superclassState;
// final ReflectionManager reflectionManager = mappings.getReflectionManager();
// do {
// classesToProcess.add( 0, currentClassInHierarchy );
// XClass superClass = currentClassInHierarchy;
// do {
// superClass = superClass.getSuperclass();
// superclassState = inheritanceStatePerClass.get( superClass );
// }
// while ( superClass != null && !reflectionManager
// .equals( superClass, Object.class ) && superclassState == null );
//
// currentClassInHierarchy = superClass;
// }
// while ( superclassState != null && superclassState.isEmbeddableSuperclass() );
// addMappedSuperClassInMetadata(
// persistentClass, annotatedClass, inheritanceStatePerClass, mappings, classesToProcess
// );
//
//
// return classesToProcess;
// }
//
// private static void addMappedSuperClassInMetadata(PersistentClass persistentClass,
// XClass annotatedClass,
// Map<XClass, InheritanceState> inheritanceStatePerClass,
// ExtendedMappings mappings,
// List<XClass> classesToProcess) {
// //add @MappedSuperclass in the metadata
// // classes from 0 to n-1 are @MappedSuperclass and should be linked
// org.hibernate.mapping.MappedSuperclass mappedSuperclass = null;
// final InheritanceState superEntityState =
// InheritanceState.getInheritanceStateOfSuperEntity( annotatedClass, inheritanceStatePerClass );
// PersistentClass superEntity =
// superEntityState != null ?
// mappings.getClass( superEntityState.getClazz().getName() ) :
// null;
// final int lastMappedSuperclass = classesToProcess.size() - 1;
// for ( int index = 0 ; index < lastMappedSuperclass ; index++ ) {
// org.hibernate.mapping.MappedSuperclass parentSuperclass = mappedSuperclass;
// final Class<?> type = mappings.getReflectionManager().toClass( classesToProcess.get( index ) );
// //add MAppedSuperclass if not already there
// mappedSuperclass = mappings.getMappedSuperclass( type );
// if (mappedSuperclass == null) {
// mappedSuperclass = new org.hibernate.mapping.MappedSuperclass(parentSuperclass, superEntity );
// mappedSuperclass.setMappedClass( type );
// mappings.addMappedSuperclass( type, mappedSuperclass );
// }
// }
// if (mappedSuperclass != null) {
// persistentClass.setSuperMappedSuperclass(mappedSuperclass);
// }
// }
/*
* Process the filters defined on the given class, as well as all filters defined
* on the MappedSuperclass(s) in the inheritance hierarchy
@ -1347,11 +1226,6 @@ public final class
}
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() );
propertyBinder.setColumns( columns );
Property prop = propertyBinder.makePropertyValueAndBind();
propertyBinder.getSimpleValueBinder().setVersion(true);
@ -1809,23 +1683,43 @@ public final class
propertyBinder.setLazy( lazy );
propertyBinder.setColumns( columns );
// if ( isIdentifierMapper ) {
// propertyBinder.setInsertable( false );
// propertyBinder.setUpdatable( false );
// }
propertyBinder.makePropertyValueAndBind();
}
if (isOverridden) {
final PropertyData mapsIdProperty = BinderHelper.getPropertyAnnotatedWithMapsId(
isId, propertyHolder, property.getName(), mappings
);
HashMap<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) classGenerators.clone();
final IdGenerator foreignGenerator = new IdGenerator();
foreignGenerator.setIdentifierGeneratorStrategy( "assigned" );
foreignGenerator.setName( "Hibernate-local--foreign generator" );
foreignGenerator.setIdentifierGeneratorStrategy( "foreign" );
foreignGenerator.addParam( "property", mapsIdProperty.getPropertyName() );
localGenerators.put( foreignGenerator.getName(), foreignGenerator );
BinderHelper.makeIdGenerator(
(SimpleValue) propertyBinder.getValue(),
foreignGenerator.getIdentifierGeneratorStrategy(),
foreignGenerator.getName(),
mappings,
localGenerators
);
}
if (isId) {
//components and regular basic types create SimpleValue objects
final SimpleValue value = ( SimpleValue ) propertyBinder.getValue();
processId(
propertyHolder,
inferredData,
value,
classGenerators,
isIdentifierMapper,
mappings
);
if ( !isOverridden ) {
processId(
propertyHolder,
inferredData,
value,
classGenerators,
isIdentifierMapper,
mappings
);
}
}
}
//init index
@ -1862,7 +1756,13 @@ public final class
}
}
private static void processId(PropertyHolder propertyHolder, PropertyData inferredData, SimpleValue idValue, HashMap<String, IdGenerator> classGenerators, boolean isIdentifierMapper, ExtendedMappings mappings) {
private static void processId(
PropertyHolder propertyHolder,
PropertyData inferredData,
SimpleValue idValue,
HashMap<String, IdGenerator> classGenerators,
boolean isIdentifierMapper,
ExtendedMappings mappings) {
if ( isIdentifierMapper ) {
throw new AnnotationException(
"@IdClass class should not have @Id nor @EmbeddedId properties: "

View File

@ -0,0 +1,22 @@
package org.hibernate.test.annotations.derivedidentities.e1.a;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.ManyToOne;
/**
* @author Emmanuel Bernard
*/
@Entity
@IdClass(DependentId.class)
public class Dependent {
@Id
String name;
// id attribute mapped by join column default
@Id
@ManyToOne
Employee emp;
}

View File

@ -0,0 +1,11 @@
package org.hibernate.test.annotations.derivedidentities.e1.a;
import java.io.Serializable;
/**
* @author Emmanuel Bernard
*/
public class DependentId implements Serializable {
String name;
long empPK; // corresponds to PK type of Employee
}

View File

@ -0,0 +1,45 @@
package org.hibernate.test.annotations.derivedidentities.e1.a;
import org.hibernate.Session;
import org.hibernate.test.annotations.TestCase;
import org.hibernate.test.util.SchemaUtil;
/**
* @author Emmanuel Bernard
*/
public class
DerivedIdentitySimpleParentIdClassDepTest extends TestCase {
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();
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
//Dependent.class,
//Employee.class
};
}
}

View File

@ -0,0 +1,14 @@
package org.hibernate.test.annotations.derivedidentities.e1.a;
import javax.persistence.Entity;
import javax.persistence.Id;
/**
* @author Emmanuel Bernard
*/
@Entity
public class Employee {
@Id
long empId;
String empName;
}

View File

@ -23,7 +23,7 @@ public class
d.emp = e;
d.id = new DependentId();
d.id.name = "Doggy";
d.id.empPK = e.empId; //FIXME not needed when foreign is enabled
//d.id.empPK = e.empId; //FIXME not needed when foreign is enabled
s.persist( d );
s.flush();
s.clear();
@ -46,7 +46,7 @@ public class
d.emp = e;
d.id = new DependentId();
d.id.name = "Doggy";
d.id.empPK = e.empId; //FIXME not needed when foreign is enabled
//d.id.empPK = e.empId; //FIXME not needed when foreign is enabled
s.persist( d );
s.flush();
s.clear();

View File

@ -25,9 +25,9 @@ public class DerivedIdentityIdClassParentEmbeddedIdDepTest extends TestCase {
d.emp = e;
d.id = new DependentId();
d.id.name = "Doggy";
d.id.empPK = new EmployeeId();
d.id.empPK.firstName = e.firstName; //FIXME not needed when foreign is enabled
d.id.empPK.lastName = e.lastName; //FIXME not needed when foreign is enabled
// d.id.empPK = new EmployeeId(); //FIXME not needed when foreign is enabled
// d.id.empPK.firstName = e.firstName; //FIXME not needed when foreign is enabled
// d.id.empPK.lastName = e.lastName; //FIXME not needed when foreign is enabled
s.persist( d );
s.flush();
s.clear();

View File

@ -25,9 +25,9 @@ public class DerivedIdentityEmbeddedIdParentEmbeddedIdDepTest extends TestCase {
d.emp = e;
d.id = new DependentId();
d.id.name = "Doggy";
d.id.empPK = new EmployeeId();
d.id.empPK.firstName = e.empId.firstName; //FIXME not needed when foreign is enabled
d.id.empPK.lastName = e.empId.lastName; //FIXME not needed when foreign is enabled
// d.id.empPK = new EmployeeId();
// d.id.empPK.firstName = e.empId.firstName; //FIXME not needed when foreign is enabled
// d.id.empPK.lastName = e.empId.lastName; //FIXME not needed when foreign is enabled
s.persist( d );
s.flush();
s.clear();

View File

@ -21,7 +21,7 @@ public class DerivedIdentitySimpleParentSimpleDepMapsIdTest extends TestCase {
s.persist( e );
MedicalHistory d = new MedicalHistory();
d.patient = e;
d.id = "aaa"; //FIXME not needed when foreign is enabled
//d.id = "aaa"; //FIXME not needed when foreign is enabled
s.persist( d );
s.flush();
s.clear();
@ -46,7 +46,7 @@ public class DerivedIdentitySimpleParentSimpleDepMapsIdTest extends TestCase {
s.persist( e );
FinancialHistory d = new FinancialHistory();
d.patient = e;
d.id = "aaa"; //FIXME not needed when foreign is enabled
//d.id = "aaa"; //FIXME not needed when foreign is enabled
s.persist( d );
s.flush();
s.clear();

View File

@ -22,9 +22,9 @@ public class DerivedIdentityIdClassParentSameIdTypeDepTest extends TestCase {
s.getTransaction().begin();
s.persist( e );
MedicalHistory d = new MedicalHistory();
d.id = new PersonId();
d.id.firstName = "Emmanuel"; //FIXME not needed when foreign is enabled
d.id.lastName = "Bernard"; //FIXME not needed when foreign is enabled
// d.id = new PersonId(); //FIXME not needed when foreign is enabled
// d.id.firstName = "Emmanuel"; //FIXME not needed when foreign is enabled
// d.id.lastName = "Bernard"; //FIXME not needed when foreign is enabled
d.patient = e;
s.persist( d );
s.flush();

View File

@ -21,9 +21,9 @@ public class DerivedIdentityEmbeddedIdParentSameIdTypeDepTest extends TestCase {
s.getTransaction().begin();
s.persist( e );
MedicalHistory d = new MedicalHistory();
d.id = new PersonId();
d.id.firstName = "Emmanuel"; //FIXME not needed when foreign is enabled
d.id.lastName = "Bernard"; //FIXME not needed when foreign is enabled
// d.id = new PersonId();
// d.id.firstName = "Emmanuel"; //FIXME not needed when foreign is enabled
// d.id.lastName = "Bernard"; //FIXME not needed when foreign is enabled
d.patient = e;
s.persist( d );
s.flush();