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:
parent
fd389b913e
commit
01720257b2
|
@ -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 ) ) {
|
||||
|
|
|
@ -195,4 +195,8 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
|
|||
public KeyValue getIdentifier() {
|
||||
return persistentClass.getIdentifier();
|
||||
}
|
||||
|
||||
public boolean isOrWithinEmbeddedId() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue