[hibernate-commits] Hibernate SVN: r18583 - in core/trunk/annotations/src: test/java/org/hibernate/test/annotations/derivedidentities and 2 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Tue Jan 19 13:57:20 EST 2010
Author: epbernard
Date: 2010-01-19 13:57:19 -0500 (Tue, 19 Jan 2010)
New Revision: 18583
Added:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/
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/MedicalHistory.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java
Modified:
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/ExtendedMappings.java
core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyContainer.java
Log:
HHH-4529 Support for basic @MapsId on simple id on both parent and derived (example 4.a). However I am losing the creation of the FK constraint.
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-19 18:50:29 UTC (rev 18582)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java 2010-01-19 18:57:19 UTC (rev 18583)
@@ -56,6 +56,7 @@
import javax.persistence.ManyToOne;
import javax.persistence.MapKey;
import javax.persistence.MappedSuperclass;
+import javax.persistence.MapsId;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
@@ -891,7 +892,7 @@
boolean hasIdentifier = false;
for ( int index = 0; index < deep; index++ ) {
- PropertyContainer properyContainer = new PropertyContainer( classesToProcess.get( index ) );
+ PropertyContainer properyContainer = new PropertyContainer( classesToProcess.get( index ), clazzToProcess );
boolean currentHasIdentifier = addElementsOfClass( elements, accessType, properyContainer, mappings );
hasIdentifier = hasIdentifier || currentHasIdentifier;
}
@@ -1116,7 +1117,7 @@
Collection<XProperty> properties = propertyContainer.getProperties( accessType );
for ( XProperty p : properties ) {
final boolean currentHasIdentifier = addProperty(
- propertyContainer.getXClass(), p, elements, accessType.getType(), mappings
+ propertyContainer, p, elements, accessType.getType(), mappings
);
hasIdentifier = hasIdentifier || currentHasIdentifier;
}
@@ -1124,9 +1125,11 @@
}
private static boolean addProperty(
- XClass declaringClass, XProperty property, List<PropertyData> annElts,
+ PropertyContainer propertyContainer, XProperty property, List<PropertyData> annElts,
String propertyAccessor, ExtendedMappings mappings
) {
+ final XClass declaringClass = propertyContainer.getDeclaringClass();
+ final XClass entity = propertyContainer.getEntityAtStake();
boolean hasIdentifier;
PropertyData propertyAnnotatedElement = new PropertyInferredData(
declaringClass, property, propertyAccessor,
@@ -1145,6 +1148,9 @@
annElts.add( propertyAnnotatedElement );
hasIdentifier = false;
}
+ if ( element.isAnnotationPresent( MapsId.class ) ) {
+ mappings.addPropertyAnnotatedWithMapsId( entity, propertyAnnotatedElement );
+ }
return hasIdentifier;
}
@@ -1166,7 +1172,7 @@
* ordering does not matter
*/
Ejb3Column[] columns = null;
- Ejb3JoinColumn[] joinColumns = null;
+
log.debug(
"Processing annotations of {}.{}", propertyHolder.getEntityName(), inferredData.getPropertyName()
);
@@ -1183,36 +1189,11 @@
}
return;
}
+ Ejb3JoinColumn[] joinColumns = buildExplicitJoinColumns(
+ propertyHolder, property, inferredData, entityBinder, mappings
+ );
- //process @JoinColumn(s) before @Column(s) to handle collection of entities properly
- {
- JoinColumn[] anns = null;
- if ( property.isAnnotationPresent( JoinColumn.class ) ) {
- anns = new JoinColumn[] { property.getAnnotation( JoinColumn.class ) };
- }
- else if ( property.isAnnotationPresent( JoinColumns.class ) ) {
- JoinColumns ann = property.getAnnotation( JoinColumns.class );
- anns = ann.value();
- int length = anns.length;
- if ( length == 0 ) {
- throw new AnnotationException( "Cannot bind an empty @JoinColumns" );
- }
- }
- if ( anns != null ) {
- joinColumns = Ejb3JoinColumn.buildJoinColumns(
- anns, null, entityBinder.getSecondaryTables(),
- propertyHolder, inferredData.getPropertyName(), mappings
- );
- }
- else if ( property.isAnnotationPresent( JoinColumnsOrFormulas.class ) ) {
- JoinColumnsOrFormulas ann = property.getAnnotation( JoinColumnsOrFormulas.class );
- joinColumns = Ejb3JoinColumn.buildJoinColumnsOrFormulas(
- ann, null, entityBinder.getSecondaryTables(),
- propertyHolder, inferredData.getPropertyName(), mappings
- );
- }
- }
if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent( Formula.class ) ) {
Column ann = property.getAnnotation( Column.class );
Formula formulaAnn = property.getAnnotation( Formula.class );
@@ -1234,30 +1215,9 @@
( property.isAnnotationPresent( ManyToOne.class )
|| property.isAnnotationPresent( OneToOne.class ) )
) {
- JoinTable joinTableAnn = propertyHolder.getJoinTable( property );
- if ( joinTableAnn != null ) {
- joinColumns = Ejb3JoinColumn.buildJoinColumns(
- joinTableAnn.inverseJoinColumns(), null, entityBinder.getSecondaryTables(),
- propertyHolder, inferredData.getPropertyName(), mappings
- );
- if ( StringHelper.isEmpty( joinTableAnn.name() ) ) {
- throw new AnnotationException(
- "JoinTable.name() on a @ToOne association has to be explicit: "
- + StringHelper.qualify( propertyHolder.getPath(), inferredData.getPropertyName() )
- );
- }
- }
- else {
- OneToOne oneToOneAnn = property.getAnnotation( OneToOne.class );
- String mappedBy = oneToOneAnn != null ?
- oneToOneAnn.mappedBy() :
- null;
- joinColumns = Ejb3JoinColumn.buildJoinColumns(
- (JoinColumn[]) null,
- mappedBy, entityBinder.getSecondaryTables(),
- propertyHolder, inferredData.getPropertyName(), mappings
- );
- }
+ joinColumns = buildDefaultJoinColumnsForXToOne(
+ propertyHolder, property, inferredData, entityBinder, mappings
+ );
}
else if ( joinColumns == null &&
( property.isAnnotationPresent( OneToMany.class )
@@ -1843,6 +1803,69 @@
}
}
+ private static Ejb3JoinColumn[] buildDefaultJoinColumnsForXToOne(PropertyHolder propertyHolder, XProperty property, PropertyData inferredData, EntityBinder entityBinder, ExtendedMappings mappings) {
+ Ejb3JoinColumn[] joinColumns;
+ JoinTable joinTableAnn = propertyHolder.getJoinTable( property );
+ if ( joinTableAnn != null ) {
+ joinColumns = Ejb3JoinColumn.buildJoinColumns(
+ joinTableAnn.inverseJoinColumns(), null, entityBinder.getSecondaryTables(),
+ propertyHolder, inferredData.getPropertyName(), mappings
+ );
+ if ( StringHelper.isEmpty( joinTableAnn.name() ) ) {
+ throw new AnnotationException(
+ "JoinTable.name() on a @ToOne association has to be explicit: "
+ + StringHelper.qualify( propertyHolder.getPath(), inferredData.getPropertyName() )
+ );
+ }
+ }
+ else {
+ OneToOne oneToOneAnn = property.getAnnotation( OneToOne.class );
+ String mappedBy = oneToOneAnn != null ?
+ oneToOneAnn.mappedBy() :
+ null;
+ joinColumns = Ejb3JoinColumn.buildJoinColumns(
+ ( JoinColumn[]) null,
+ mappedBy, entityBinder.getSecondaryTables(),
+ propertyHolder, inferredData.getPropertyName(), mappings
+ );
+ }
+ return joinColumns;
+ }
+
+ private static Ejb3JoinColumn[] buildExplicitJoinColumns(PropertyHolder propertyHolder, XProperty property, PropertyData inferredData, EntityBinder entityBinder, ExtendedMappings mappings) {
+ //process @JoinColumn(s) before @Column(s) to handle collection of entities properly
+ Ejb3JoinColumn[] joinColumns = null;
+ {
+ JoinColumn[] anns = null;
+
+ if ( property.isAnnotationPresent( JoinColumn.class ) ) {
+ anns = new JoinColumn[] { property.getAnnotation( JoinColumn.class ) };
+ }
+ else if ( property.isAnnotationPresent( JoinColumns.class ) ) {
+ JoinColumns ann = property.getAnnotation( JoinColumns.class );
+ anns = ann.value();
+ int length = anns.length;
+ if ( length == 0 ) {
+ throw new AnnotationException( "Cannot bind an empty @JoinColumns" );
+ }
+ }
+ if ( anns != null ) {
+ joinColumns = Ejb3JoinColumn.buildJoinColumns(
+ anns, null, entityBinder.getSecondaryTables(),
+ propertyHolder, inferredData.getPropertyName(), mappings
+ );
+ }
+ else if ( property.isAnnotationPresent( JoinColumnsOrFormulas.class ) ) {
+ JoinColumnsOrFormulas ann = property.getAnnotation( JoinColumnsOrFormulas.class );
+ joinColumns = Ejb3JoinColumn.buildJoinColumnsOrFormulas(
+ ann, null, entityBinder.getSecondaryTables(),
+ propertyHolder, inferredData.getPropertyName(), mappings
+ );
+ }
+ }
+ return joinColumns;
+ }
+
//TODO move that to collection binder?
private static void bindJoinedTableAssociation(
XProperty property, ExtendedMappings mappings, EntityBinder entityBinder,
@@ -1979,6 +2002,7 @@
inferredData, propertyHolder, mappings
);
+ final XClass entityXClass = inferredData.getPropertyClass();
List<PropertyData> classElements = new ArrayList<PropertyData>();
XClass returnedClassOrElement = inferredData.getClassOrElement();
@@ -1989,25 +2013,25 @@
baseClassElements = new ArrayList<PropertyData>();
baseReturnedClassOrElement = baseInferredData.getClassOrElement();
bindTypeDefs(baseReturnedClassOrElement, mappings);
- PropertyContainer propContainer = new PropertyContainer( baseReturnedClassOrElement );
+ PropertyContainer propContainer = new PropertyContainer( baseReturnedClassOrElement, entityXClass );
addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );
}
//embeddable elements can have type defs
bindTypeDefs(returnedClassOrElement, mappings);
- PropertyContainer propContainer = new PropertyContainer( returnedClassOrElement );
+ PropertyContainer propContainer = new PropertyContainer( returnedClassOrElement, entityXClass );
addElementsOfClass( classElements, propertyAccessor, propContainer, mappings);
//add elements of the embeddable superclass
- XClass superClass = inferredData.getPropertyClass().getSuperclass();
+ XClass superClass = entityXClass.getSuperclass();
while ( superClass != null && superClass.isAnnotationPresent( MappedSuperclass.class ) ) {
//FIXME: proper support of typevariables incl var resolved at upper levels
- propContainer = new PropertyContainer( superClass );
+ propContainer = new PropertyContainer( superClass, entityXClass );
addElementsOfClass( classElements, propertyAccessor, propContainer, mappings );
superClass = superClass.getSuperclass();
}
if ( baseClassElements != null ) {
- if ( !hasIdClassAnnotations( inferredData.getPropertyClass() ) ) {
+ if ( !hasIdClassAnnotations( entityXClass ) ) {
for ( int i = 0; i < classElements.size(); i++ ) {
classElements.set( i, baseClassElements.get( i ) ); //this works since they are in the same order
}
@@ -2082,6 +2106,22 @@
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 );
+ }
+ }
+
for (Ejb3Column column : columns) {
column.forceNotNull(); //this is an id
}
Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java 2010-01-19 18:50:29 UTC (rev 18582)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java 2010-01-19 18:57:19 UTC (rev 18583)
@@ -46,6 +46,7 @@
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
+import javax.persistence.MapsId;
import org.dom4j.Attribute;
import org.dom4j.Document;
@@ -64,6 +65,7 @@
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.common.reflection.MetadataProvider;
@@ -141,6 +143,7 @@
private transient ReflectionManager reflectionManager;
private boolean isDefaultProcessed = false;
private boolean isValidatorNotPresentLogged;
+ private Map<XClass,Map<String,PropertyData>> propertiesAnnotatedWithMapsId;
public AnnotationConfiguration() {
super();
@@ -279,6 +282,7 @@
namingStrategy = EJB3NamingStrategy.INSTANCE;
setEntityResolver( new EJB3DTDEntityResolver() );
anyMetaDefs = new HashMap<String, AnyMetaDef>();
+ propertiesAnnotatedWithMapsId = new HashMap<XClass, Map<String,PropertyData>>();
reflectionManager = new JavaReflectionManager();
( ( MetadataProviderInjector ) reflectionManager ).setMetadataProvider( new JPAMetadataProvider() );
@@ -1271,6 +1275,20 @@
return inSecondPass;
}
+ public PropertyData getPropertyAnnotatedWithMapsId(XClass entityType, String propertyName) {
+ final Map<String, PropertyData> map = propertiesAnnotatedWithMapsId.get( entityType );
+ return map == null ? null : map.get( propertyName );
+ }
+
+ public void addPropertyAnnotatedWithMapsId(XClass entityType, PropertyData property) {
+ Map<String, PropertyData> map = propertiesAnnotatedWithMapsId.get( entityType );
+ if (map == null) {
+ map = new HashMap<String, PropertyData>();
+ propertiesAnnotatedWithMapsId.put( entityType, map );
+ }
+ map.put( property.getProperty().getAnnotation( MapsId.class ).value(), property );
+ }
+
public IdGenerator getGenerator(String name) {
return getGenerator( name, null );
}
Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java 2010-01-19 18:50:29 UTC (rev 18582)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java 2010-01-19 18:57:19 UTC (rev 18583)
@@ -171,4 +171,12 @@
public AnyMetaDef getAnyMetaDef(String name);
public boolean isInSecondPass();
+
+ /**
+ * Return the property annotated with @MapsId("propertyName") if any.
+ * Null otherwise
+ */
+ public PropertyData getPropertyAnnotatedWithMapsId(XClass entityType, String propertyName);
+
+ public void addPropertyAnnotatedWithMapsId(XClass entityType, PropertyData property);
}
\ No newline at end of file
Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyContainer.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyContainer.java 2010-01-19 18:50:29 UTC (rev 18582)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyContainer.java 2010-01-19 18:57:19 UTC (rev 18583)
@@ -1,4 +1,4 @@
-// $Id:$
+// $Id$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@@ -55,20 +55,26 @@
class PropertyContainer {
private static final Logger log = LoggerFactory.getLogger( AnnotationBinder.class );
+ private final XClass entityAtStake;
private final TreeMap<String, XProperty> fieldAccessMap;
private final TreeMap<String, XProperty> propertyAccessMap;
private final XClass xClass;
private final AccessType explicitClassDefinedAccessType;
- PropertyContainer(XClass clazz) {
+ PropertyContainer(XClass clazz, XClass entityAtStake) {
this.xClass = clazz;
+ this.entityAtStake = entityAtStake;
fieldAccessMap = initProperties( AccessType.FIELD );
propertyAccessMap = initProperties( AccessType.PROPERTY );
explicitClassDefinedAccessType = determineClassDefinedAccessStrategy();
checkForJpaAccess();
}
- public XClass getXClass() {
+ public XClass getEntityAtStake() {
+ return entityAtStake;
+ }
+
+ public XClass getDeclaringClass() {
return xClass;
}
Added: 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/DerivedIdentitySimpleParentSimpleDepTest.java (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java 2010-01-19 18:57:19 UTC (rev 18583)
@@ -0,0 +1,42 @@
+package org.hibernate.test.annotations.derivedidentities.e4.a;
+
+import org.hibernate.Session;
+import org.hibernate.test.annotations.TestCase;
+import org.hibernate.test.annotations.derivedidentities.e1.b.Dependent;
+import org.hibernate.test.annotations.derivedidentities.e1.b.DependentId;
+import org.hibernate.test.annotations.derivedidentities.e1.b.Employee;
+import org.hibernate.test.util.SchemaUtil;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class DerivedIdentitySimpleParentSimpleDepTest extends TestCase {
+
+ public void testIt() 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;
+ d.id = "aaa"; //FIXME not needed when foreign is enabled
+ s.persist( d );
+ s.flush();
+ s.clear();
+ d = (MedicalHistory) s.get( MedicalHistory.class, d.id );
+ assertEquals( d.id, d.patient.ssn );
+ s.getTransaction().rollback();
+ s.close();
+ }
+
+ @Override
+ protected Class<?>[] getMappings() {
+ return new Class<?>[] {
+ MedicalHistory.class,
+ Person.class
+ };
+ }
+}
\ No newline at end of file
Added: 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/MedicalHistory.java (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/MedicalHistory.java 2010-01-19 18:57:19 UTC (rev 18583)
@@ -0,0 +1,20 @@
+package org.hibernate.test.annotations.derivedidentities.e4.a;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.MapsId;
+import javax.persistence.OneToOne;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+public class MedicalHistory {
+ @Id
+ String id; // overriding not allowed ... // default join column name is overridden @MapsId
+ @JoinColumn(name = "FK")
+ @MapsId
+ @OneToOne
+ Person patient;
+}
Added: 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/Person.java (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java 2010-01-19 18:57:19 UTC (rev 18583)
@@ -0,0 +1,13 @@
+package org.hibernate.test.annotations.derivedidentities.e4.a;
+
+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
More information about the hibernate-commits
mailing list