HHH-4529 Add support for @EmbeddedId

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18590 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Emmanuel Bernard 2010-01-20 18:36:34 +00:00
parent fd389b913e
commit 01720257b2
8 changed files with 95 additions and 43 deletions

View File

@ -1256,6 +1256,8 @@ public final class AnnotationBinder {
if ( !entityBinder.isIgnoreIdAnnotations() &&
( property.isAnnotationPresent( Id.class )
|| property.isAnnotationPresent( EmbeddedId.class ) ) ) {
//Override from @MapsId if needed
columns = overrideColumnFromMapsIdProperty( "", columns, propertyHolder, entityBinder, mappings );
if ( isIdentifierMapper ) {
throw new AnnotationException(
"@IdClass class should not have @Id nor @EmbeddedId properties"
@ -1754,6 +1756,12 @@ public final class AnnotationBinder {
}
}
//Override from @MapsId if needed
if ( propertyHolder.isOrWithinEmbeddedId() ) {
columns = overrideColumnFromMapsIdProperty( property.getName(), columns, propertyHolder, entityBinder, mappings );
}
PropertyBinder propBinder = new PropertyBinder();
propBinder.setName( inferredData.getPropertyName() );
propBinder.setReturnedClassName( inferredData.getTypeName() );
@ -2110,25 +2118,6 @@ public final class AnnotationBinder {
setupComponentTuplizer( property, componentId );
}
else {
final XClass persistentXClass;
try {
persistentXClass = mappings.getReflectionManager()
.classForName( persistentClassName, AnnotationBinder.class );
}
catch ( ClassNotFoundException e ) {
throw new AssertionFailure( "Persistence class name cannot be converted into a Class", e);
}
final PropertyData annotatedWithMapsId = mappings.getPropertyAnnotatedWithMapsId( persistentXClass, "" );
if ( annotatedWithMapsId != null ) {
columns = buildExplicitJoinColumns( propertyHolder, annotatedWithMapsId.getProperty(), annotatedWithMapsId, entityBinder, mappings );
if (columns == null) {
columns = buildDefaultJoinColumnsForXToOne( propertyHolder, annotatedWithMapsId.getProperty(), annotatedWithMapsId, entityBinder, mappings );
throw new UnsupportedOperationException( "Implicit @JoinColumn is not supported on @MapsId properties: "
+ annotatedWithMapsId.getDeclaringClass() + " " + annotatedWithMapsId.getPropertyName() );
}
}
for (Ejb3Column column : columns) {
column.forceNotNull(); //this is an id
}
@ -2170,6 +2159,32 @@ public final class AnnotationBinder {
}
}
private static Ejb3Column[] overrideColumnFromMapsIdProperty(String propertyPath,
Ejb3Column[] columns,
PropertyHolder propertyHolder,
EntityBinder entityBinder,
ExtendedMappings mappings) {
Ejb3Column[] result = columns;
final XClass persistentXClass;
try {
persistentXClass = mappings.getReflectionManager()
.classForName( propertyHolder.getPersistentClass().getClassName(), AnnotationBinder.class );
}
catch ( ClassNotFoundException e ) {
throw new AssertionFailure( "PersistentClass name cannot be converted into a Class", e);
}
final PropertyData annotatedWithMapsId = mappings.getPropertyAnnotatedWithMapsId( persistentXClass, propertyPath );
if ( annotatedWithMapsId != null ) {
result = buildExplicitJoinColumns( propertyHolder, annotatedWithMapsId.getProperty(), annotatedWithMapsId, entityBinder, mappings );
if (result == null) {
result = buildDefaultJoinColumnsForXToOne( propertyHolder, annotatedWithMapsId.getProperty(), annotatedWithMapsId, entityBinder, mappings );
throw new UnsupportedOperationException( "Implicit @JoinColumn is not supported on @MapsId properties: "
+ annotatedWithMapsId.getDeclaringClass() + " " + annotatedWithMapsId.getPropertyName() );
}
}
return result;
}
private static void setupComponentTuplizer(XProperty property, Component component) {
if ( property == null ) return;
if ( property.isAnnotationPresent( Tuplizers.class ) ) {

View File

@ -195,4 +195,8 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
public KeyValue getIdentifier() {
return persistentClass.getIdentifier();
}
public boolean isOrWithinEmbeddedId() {
return false;
}
}

View File

@ -70,6 +70,10 @@ public class CollectionPropertyHolder extends AbstractPropertyHolder {
throw new AssertionFailure( "Identifier collection not yet managed" );
}
public boolean isOrWithinEmbeddedId() {
return false;
}
public PersistentClass getPersistentClass() {
return collection.getOwner();
}

View File

@ -24,11 +24,14 @@
package org.hibernate.cfg;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.KeyValue;
@ -45,6 +48,7 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
//TODO introduce a overrideTable() method for columns held by sec table rather than the hack
// joinsPerRealTableName in ClassPropertyHolder
private Component component;
private boolean isOrWithinEmbeddedId;
public String getEntityName() {
return component.getComponentClassName();
@ -82,8 +86,14 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
ExtendedMappings mappings
) {
super( path, parent, inferredData.getPropertyClass(), mappings );
setCurrentProperty( inferredData.getProperty() );
final XProperty property = inferredData.getProperty();
setCurrentProperty( property );
this.component = component;
this.isOrWithinEmbeddedId =
parent.isOrWithinEmbeddedId()
|| ( property != null &&
( property.isAnnotationPresent( Id.class )
|| property.isAnnotationPresent( EmbeddedId.class ) ) );
}
public String getClassName() {
@ -106,6 +116,10 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
return component.getOwner().getIdentifier();
}
public boolean isOrWithinEmbeddedId() {
return isOrWithinEmbeddedId;
}
public PersistentClass getPersistentClass() {
return component.getOwner();
}

View File

@ -53,6 +53,11 @@ public interface PropertyHolder {
KeyValue getIdentifier();
/**
* Return true if this component is or is embedded in a @EmbeddedId
*/
boolean isOrWithinEmbeddedId();
PersistentClass getPersistentClass();
boolean isComponent();

View File

@ -44,6 +44,15 @@ public class PropertyInferredData implements PropertyData {
private final ReflectionManager reflectionManager;
private final XClass declaringClass;
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "PropertyInferredData" );
sb.append( "{property=" ).append( property );
sb.append( ", declaringClass=" ).append( declaringClass );
sb.append( '}' );
return sb.toString();
}
/**
* Take the annoted element for lazy process

View File

@ -2,6 +2,7 @@ package org.hibernate.test.annotations.derivedidentities.e1.b;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapsId;
@ -13,7 +14,7 @@ public class Dependent {
@EmbeddedId
DependentId id;
// id attribute mapped by join column default
@JoinColumn(name="FK") // id attribute mapped by join column default
@MapsId("empPK") // maps empPK attribute of embedded id
@ManyToOne
Employee emp;

View File

@ -9,28 +9,28 @@ import org.hibernate.test.util.SchemaUtil;
*/
public class DerivedIdentitySimpleParentEmbeddedIdDepTest extends TestCase {
// public void testIt() throws Exception {
// assertTrue( SchemaUtil.isColumnPresent( "Dependent", "empPK", getCfg() ) );
// assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "emp_empId", 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.id = new DependentId();
// d.id.name = "Doggy";
// d.id.empPK = e.empId; //FIXME not needed when foreign is enabled
// s.persist( d );
// s.flush();
// s.clear();
// d = (Dependent) s.get( Dependent.class, d.id );
// assertEquals( d.id.empPK, d.emp.empId );
// s.getTransaction().rollback();
// s.close();
// }
public void testIt() 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.id = new DependentId();
d.id.name = "Doggy";
d.id.empPK = e.empId; //FIXME not needed when foreign is enabled
s.persist( d );
s.flush();
s.clear();
d = (Dependent) s.get( Dependent.class, d.id );
assertEquals( d.id.empPK, d.emp.empId );
s.getTransaction().rollback();
s.close();
}
@Override
protected Class<?>[] getMappings() {