HHH-4529 clean @Id/@EmbeddedId mapping and merge with the regular basic and component mapping to open possibilities for @Id @ManyToOne support
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18600 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
174a568f8f
commit
8577a68e69
|
@ -1253,27 +1253,11 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
final XClass returnedClass = inferredData.getClassOrElement();
|
final XClass returnedClass = inferredData.getClassOrElement();
|
||||||
boolean isId;
|
|
||||||
if ( !entityBinder.isIgnoreIdAnnotations() &&
|
boolean isId = !entityBinder.isIgnoreIdAnnotations() &&
|
||||||
( property.isAnnotationPresent( Id.class )
|
( property.isAnnotationPresent( Id.class )
|
||||||
|| property.isAnnotationPresent( EmbeddedId.class ) ) ) {
|
|| property.isAnnotationPresent( EmbeddedId.class ) );
|
||||||
isId = true;
|
if ( property.isAnnotationPresent( Version.class ) ) {
|
||||||
//Override from @MapsId if needed
|
|
||||||
columns = overrideColumnFromMapsIdProperty( "", columns, propertyHolder, entityBinder, mappings );
|
|
||||||
processId(
|
|
||||||
propertyHolder,
|
|
||||||
property,
|
|
||||||
inferredData,
|
|
||||||
classGenerators,
|
|
||||||
entityBinder,
|
|
||||||
isIdentifierMapper,
|
|
||||||
mappings,
|
|
||||||
inheritanceStatePerClass,
|
|
||||||
columns,
|
|
||||||
returnedClass
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if ( property.isAnnotationPresent( Version.class ) ) {
|
|
||||||
if ( isIdentifierMapper ) {
|
if ( isIdentifierMapper ) {
|
||||||
throw new AnnotationException(
|
throw new AnnotationException(
|
||||||
"@IdClass class should not have @Version property"
|
"@IdClass class should not have @Version property"
|
||||||
|
@ -1304,7 +1288,7 @@ public final class AnnotationBinder {
|
||||||
propBinder.setReturnedClass( inferredData.getPropertyClass() );
|
propBinder.setReturnedClass( inferredData.getPropertyClass() );
|
||||||
propBinder.setMappings( mappings );
|
propBinder.setMappings( mappings );
|
||||||
propBinder.setDeclaringClass( inferredData.getDeclaringClass() );
|
propBinder.setDeclaringClass( inferredData.getDeclaringClass() );
|
||||||
Property prop = propBinder.bind();
|
Property prop = propBinder.makePropertyValueAndBind();
|
||||||
propBinder.getSimpleValueBinder().setVersion(true);
|
propBinder.getSimpleValueBinder().setVersion(true);
|
||||||
rootClass.setVersion( prop );
|
rootClass.setVersion( prop );
|
||||||
|
|
||||||
|
@ -1695,19 +1679,26 @@ public final class AnnotationBinder {
|
||||||
collectionBinder.bind();
|
collectionBinder.bind();
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
//Either a regular property or a basic @Id or @EmbeddedId while not ignoring id annotations
|
||||||
|
else if ( !isId || !entityBinder.isIgnoreIdAnnotations() ) {
|
||||||
//define whether the type is a component or not
|
//define whether the type is a component or not
|
||||||
boolean isComponent;
|
boolean isComponent;
|
||||||
Embeddable embeddableAnn = returnedClass.getAnnotation( Embeddable.class );
|
isComponent = property.isAnnotationPresent( Embedded.class )
|
||||||
Embedded embeddedAnn = property.getAnnotation( Embedded.class );
|
|| property.isAnnotationPresent( EmbeddedId.class )
|
||||||
isComponent = embeddedAnn != null || embeddableAnn != null;
|
|| returnedClass.isAnnotationPresent( Embeddable.class );
|
||||||
|
PropertyBinder propertyBinder;
|
||||||
if ( isComponent ) {
|
if ( isComponent ) {
|
||||||
AccessType propertyAccessor = entityBinder.getPropertyAccessor( property );
|
AccessType propertyAccessor = entityBinder.getPropertyAccessor( property );
|
||||||
bindComponent(
|
propertyBinder = bindComponent(
|
||||||
inferredData, propertyHolder, propertyAccessor, entityBinder,
|
inferredData,
|
||||||
|
propertyHolder,
|
||||||
|
propertyAccessor,
|
||||||
|
entityBinder,
|
||||||
isIdentifierMapper,
|
isIdentifierMapper,
|
||||||
mappings, isComponentEmbedded, inheritanceStatePerClass
|
mappings,
|
||||||
|
isComponentEmbedded,
|
||||||
|
isId,
|
||||||
|
inheritanceStatePerClass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1720,35 +1711,53 @@ public final class AnnotationBinder {
|
||||||
lazy = ann.fetch() == FetchType.LAZY;
|
lazy = ann.fetch() == FetchType.LAZY;
|
||||||
}
|
}
|
||||||
//implicit type will check basic types and Serializable classes
|
//implicit type will check basic types and Serializable classes
|
||||||
if ( !optional && nullability != Nullability.FORCED_NULL ) {
|
if ( isId || ( !optional && nullability != Nullability.FORCED_NULL ) ) {
|
||||||
//force columns to not null
|
//force columns to not null
|
||||||
for (Ejb3Column col : columns) {
|
for (Ejb3Column col : columns) {
|
||||||
col.forceNotNull();
|
col.forceNotNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Override from @MapsId if needed
|
//Override from @MapsId if needed
|
||||||
if ( propertyHolder.isOrWithinEmbeddedId() ) {
|
if ( isId || propertyHolder.isOrWithinEmbeddedId() ) {
|
||||||
columns = overrideColumnFromMapsIdProperty( property.getName(), columns, propertyHolder, entityBinder, mappings );
|
columns = overrideColumnFromMapsIdProperty(
|
||||||
|
isId ? "" : property.getName(), //@MapsId("") points to the id property
|
||||||
|
columns,
|
||||||
|
propertyHolder,
|
||||||
|
entityBinder,
|
||||||
|
mappings );
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyBinder propBinder = new PropertyBinder();
|
propertyBinder = new PropertyBinder();
|
||||||
propBinder.setName( inferredData.getPropertyName() );
|
propertyBinder.setName( inferredData.getPropertyName() );
|
||||||
propBinder.setReturnedClassName( inferredData.getTypeName() );
|
propertyBinder.setReturnedClassName( inferredData.getTypeName() );
|
||||||
propBinder.setLazy( lazy );
|
propertyBinder.setLazy( lazy );
|
||||||
propBinder.setAccessType( inferredData.getDefaultAccess() );
|
propertyBinder.setAccessType( inferredData.getDefaultAccess() );
|
||||||
propBinder.setColumns( columns );
|
propertyBinder.setColumns( columns );
|
||||||
propBinder.setHolder( propertyHolder );
|
propertyBinder.setHolder( propertyHolder );
|
||||||
propBinder.setProperty( property );
|
propertyBinder.setProperty( property );
|
||||||
propBinder.setReturnedClass( inferredData.getPropertyClass() );
|
propertyBinder.setReturnedClass( inferredData.getPropertyClass() );
|
||||||
propBinder.setMappings( mappings );
|
propertyBinder.setMappings( mappings );
|
||||||
if ( isIdentifierMapper ) {
|
if ( isIdentifierMapper ) {
|
||||||
propBinder.setInsertable( false );
|
propertyBinder.setInsertable( false );
|
||||||
propBinder.setUpdatable( false );
|
propertyBinder.setUpdatable( false );
|
||||||
}
|
}
|
||||||
propBinder.setDeclaringClass( inferredData.getDeclaringClass() );
|
propertyBinder.setDeclaringClass( inferredData.getDeclaringClass() );
|
||||||
propBinder.bind();
|
propertyBinder.setId(isId);
|
||||||
|
propertyBinder.setInheritanceStatePerClass(inheritanceStatePerClass);
|
||||||
|
propertyBinder.makePropertyValueAndBind();
|
||||||
|
}
|
||||||
|
if (isId) {
|
||||||
|
//components and regular basic types create SimpleValue objects
|
||||||
|
final SimpleValue value = ( SimpleValue ) propertyBinder.getValue();
|
||||||
|
processId(
|
||||||
|
propertyHolder,
|
||||||
|
inferredData,
|
||||||
|
value,
|
||||||
|
classGenerators,
|
||||||
|
isIdentifierMapper,
|
||||||
|
mappings
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//init index
|
//init index
|
||||||
|
@ -1785,14 +1794,15 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processId(PropertyHolder propertyHolder, XProperty property, PropertyData inferredData, HashMap<String, IdGenerator> classGenerators, EntityBinder entityBinder, boolean isIdentifierMapper, ExtendedMappings mappings, Map<XClass, InheritanceState> inheritanceStatePerClass, Ejb3Column[] columns, XClass returnedClass) {
|
private static void processId(PropertyHolder propertyHolder, PropertyData inferredData, SimpleValue idValue, HashMap<String, IdGenerator> classGenerators, boolean isIdentifierMapper, ExtendedMappings mappings) {
|
||||||
if ( isIdentifierMapper ) {
|
if ( isIdentifierMapper ) {
|
||||||
throw new AnnotationException(
|
throw new AnnotationException(
|
||||||
"@IdClass class should not have @Id nor @EmbeddedId properties: "
|
"@IdClass class should not have @Id nor @EmbeddedId properties: "
|
||||||
+ BinderHelper.getPath( propertyHolder, inferredData )
|
+ BinderHelper.getPath( propertyHolder, inferredData )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
log.trace( "{} is an id", inferredData.getPropertyName() );
|
XClass returnedClass = inferredData.getClassOrElement();
|
||||||
|
XProperty property = inferredData.getProperty();
|
||||||
//clone classGenerator and override with local values
|
//clone classGenerator and override with local values
|
||||||
HashMap<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) classGenerators.clone();
|
HashMap<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) classGenerators.clone();
|
||||||
localGenerators.putAll( buildLocalGenerators( property, mappings ) );
|
localGenerators.putAll( buildLocalGenerators( property, mappings ) );
|
||||||
|
@ -1801,31 +1811,16 @@ public final class AnnotationBinder {
|
||||||
//guess if its a component and find id data access (property, field etc)
|
//guess if its a component and find id data access (property, field etc)
|
||||||
final boolean isComponent = returnedClass.isAnnotationPresent( Embeddable.class )
|
final boolean isComponent = returnedClass.isAnnotationPresent( Embeddable.class )
|
||||||
|| property.isAnnotationPresent( EmbeddedId.class );
|
|| property.isAnnotationPresent( EmbeddedId.class );
|
||||||
AccessType propertyAccessor = entityBinder.getPropertyAccessor( returnedClass );
|
|
||||||
|
|
||||||
GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
|
GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
|
||||||
String generatorType = generatedValue != null ?
|
String generatorType = generatedValue != null ?
|
||||||
generatorType( generatedValue.strategy() ) :
|
generatorType( generatedValue.strategy() ) :
|
||||||
"assigned";
|
"assigned";
|
||||||
String generator = generatedValue != null ?
|
String generatorName = generatedValue != null ?
|
||||||
generatedValue.generator() :
|
generatedValue.generator() :
|
||||||
BinderHelper.ANNOTATION_STRING_DEFAULT;
|
BinderHelper.ANNOTATION_STRING_DEFAULT;
|
||||||
if ( isComponent ) generatorType = "assigned"; //a component must not have any generator
|
if ( isComponent ) generatorType = "assigned"; //a component must not have any generator
|
||||||
|
BinderHelper.makeIdGenerator( idValue, generatorType, generatorName, mappings, localGenerators );
|
||||||
bindId(
|
|
||||||
generatorType,
|
|
||||||
generator,
|
|
||||||
inferredData,
|
|
||||||
columns,
|
|
||||||
propertyHolder,
|
|
||||||
localGenerators,
|
|
||||||
isComponent,
|
|
||||||
propertyAccessor, entityBinder,
|
|
||||||
false,
|
|
||||||
isIdentifierMapper,
|
|
||||||
mappings,
|
|
||||||
inheritanceStatePerClass
|
|
||||||
);
|
|
||||||
|
|
||||||
log.trace(
|
log.trace(
|
||||||
"Bind {} on {}", ( isComponent ? "@EmbeddedId" : "@Id" ), inferredData.getPropertyName()
|
"Bind {} on {}", ( isComponent ? "@EmbeddedId" : "@Id" ), inferredData.getPropertyName()
|
||||||
|
@ -1963,29 +1958,50 @@ public final class AnnotationBinder {
|
||||||
collectionBinder.setInverseJoinColumns( inverseJoinColumns );
|
collectionBinder.setInverseJoinColumns( inverseJoinColumns );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindComponent(
|
private static PropertyBinder bindComponent(
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
AccessType propertyAccessor, EntityBinder entityBinder,
|
AccessType propertyAccessor,
|
||||||
|
EntityBinder entityBinder,
|
||||||
boolean isIdentifierMapper,
|
boolean isIdentifierMapper,
|
||||||
ExtendedMappings mappings, boolean isComponentEmbedded,
|
ExtendedMappings mappings,
|
||||||
|
boolean isComponentEmbedded,
|
||||||
|
boolean isId,
|
||||||
Map<XClass, InheritanceState> inheritanceStatePerClass
|
Map<XClass, InheritanceState> inheritanceStatePerClass
|
||||||
) {
|
) {
|
||||||
Component comp = fillComponent(
|
Component comp = fillComponent(
|
||||||
propertyHolder, inferredData, propertyAccessor, true, entityBinder,
|
propertyHolder, inferredData, propertyAccessor, !isId, entityBinder,
|
||||||
isComponentEmbedded, isIdentifierMapper,
|
isComponentEmbedded, isIdentifierMapper,
|
||||||
false, mappings, inheritanceStatePerClass
|
false, mappings, inheritanceStatePerClass
|
||||||
);
|
);
|
||||||
|
if (isId) {
|
||||||
|
comp.setKey( true );
|
||||||
|
if ( propertyHolder.getPersistentClass().getIdentifier() != null ) {
|
||||||
|
throw new AnnotationException(
|
||||||
|
comp.getComponentClassName()
|
||||||
|
+ " must not have @Id properties when used as an @EmbeddedId: "
|
||||||
|
+ BinderHelper.getPath( propertyHolder, inferredData ) );
|
||||||
|
}
|
||||||
|
if ( comp.getPropertySpan() == 0 ) {
|
||||||
|
throw new AnnotationException( comp.getComponentClassName()
|
||||||
|
+ " has no persistent id property"
|
||||||
|
+ BinderHelper.getPath( propertyHolder, inferredData ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
XProperty property = inferredData.getProperty();
|
XProperty property = inferredData.getProperty();
|
||||||
setupComponentTuplizer( property, comp );
|
setupComponentTuplizer( property, comp );
|
||||||
|
|
||||||
PropertyBinder binder = new PropertyBinder();
|
PropertyBinder binder = new PropertyBinder();
|
||||||
binder.setName( inferredData.getPropertyName() );
|
binder.setName( inferredData.getPropertyName() );
|
||||||
binder.setValue( comp );
|
binder.setValue( comp );
|
||||||
binder.setProperty( inferredData.getProperty() );
|
binder.setProperty( inferredData.getProperty() );
|
||||||
binder.setAccessType( inferredData.getDefaultAccess() );
|
binder.setAccessType( inferredData.getDefaultAccess() );
|
||||||
Property prop = binder.make();
|
binder.setEmbedded( isComponentEmbedded );
|
||||||
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
|
binder.setHolder( propertyHolder );
|
||||||
|
binder.setId( isId );
|
||||||
|
binder.setInheritanceStatePerClass( inheritanceStatePerClass );
|
||||||
|
binder.setMappings( mappings );
|
||||||
|
binder.makePropertyAndBind();
|
||||||
|
return binder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Component fillComponent(
|
public static Component fillComponent(
|
||||||
|
@ -2159,7 +2175,7 @@ public final class AnnotationBinder {
|
||||||
binder.setValue( id );
|
binder.setValue( id );
|
||||||
binder.setAccessType( inferredData.getDefaultAccess() );
|
binder.setAccessType( inferredData.getDefaultAccess() );
|
||||||
binder.setProperty( inferredData.getProperty() );
|
binder.setProperty( inferredData.getProperty() );
|
||||||
Property prop = binder.make();
|
Property prop = binder.makeProperty();
|
||||||
rootClass.setIdentifierProperty( prop );
|
rootClass.setIdentifierProperty( prop );
|
||||||
//if the id property is on a superclass, update the metamodel
|
//if the id property is on a superclass, update the metamodel
|
||||||
final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(
|
final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(
|
||||||
|
@ -2291,7 +2307,7 @@ public final class AnnotationBinder {
|
||||||
binder.setAccessType( inferredData.getDefaultAccess() );
|
binder.setAccessType( inferredData.getDefaultAccess() );
|
||||||
binder.setCascade( cascadeStrategy );
|
binder.setCascade( cascadeStrategy );
|
||||||
binder.setProperty( property );
|
binder.setProperty( property );
|
||||||
Property prop = binder.make();
|
Property prop = binder.makeProperty();
|
||||||
//composite FK columns are in the same table so its OK
|
//composite FK columns are in the same table so its OK
|
||||||
propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
|
propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
|
||||||
}
|
}
|
||||||
|
@ -2446,7 +2462,7 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
binder.setAccessType( inferredData.getDefaultAccess() );
|
binder.setAccessType( inferredData.getDefaultAccess() );
|
||||||
binder.setCascade( cascadeStrategy );
|
binder.setCascade( cascadeStrategy );
|
||||||
Property prop = binder.make();
|
Property prop = binder.makeProperty();
|
||||||
//composite FK columns are in the same table so its OK
|
//composite FK columns are in the same table so its OK
|
||||||
propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
|
propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
|
||||||
|
|
||||||
public void addProperty(Property prop, Ejb3Column[] columns, XClass declaringClass) {
|
public void addProperty(Property prop, Ejb3Column[] columns, XClass declaringClass) {
|
||||||
//Ejb3Column.checkPropertyConsistency( ); //already called earlier
|
//Ejb3Column.checkPropertyConsistency( ); //already called earlier
|
||||||
if ( columns[0].isSecondary() ) {
|
if ( columns != null && columns[0].isSecondary() ) {
|
||||||
//TODO move the getJoin() code here?
|
//TODO move the getJoin() code here?
|
||||||
final Join join = columns[0].getJoin();
|
final Join join = columns[0].getJoin();
|
||||||
addPropertyToJoin( prop, declaringClass, join );
|
addPropertyToJoin( prop, declaringClass, join );
|
||||||
|
|
|
@ -61,6 +61,7 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
|
||||||
* if not, change the component table if no properties are set
|
* if not, change the component table if no properties are set
|
||||||
* if a property is set already the core cannot support that
|
* if a property is set already the core cannot support that
|
||||||
*/
|
*/
|
||||||
|
if (columns != null) {
|
||||||
Table table = columns[0].getTable();
|
Table table = columns[0].getTable();
|
||||||
if ( !table.equals( component.getTable() ) ) {
|
if ( !table.equals( component.getTable() ) ) {
|
||||||
if ( component.getPropertySpan() == 0 ) {
|
if ( component.getPropertySpan() == 0 ) {
|
||||||
|
@ -73,6 +74,7 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
addProperty( prop, declaringClass );
|
addProperty( prop, declaringClass );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class OneToOneSecondPass implements SecondPass {
|
||||||
binder.setValue( value );
|
binder.setValue( value );
|
||||||
binder.setCascade( cascadeStrategy );
|
binder.setCascade( cascadeStrategy );
|
||||||
binder.setAccessType( inferredData.getDefaultAccess() );
|
binder.setAccessType( inferredData.getDefaultAccess() );
|
||||||
Property prop = binder.make();
|
Property prop = binder.makeProperty();
|
||||||
if ( BinderHelper.isDefault( mappedBy ) ) {
|
if ( BinderHelper.isDefault( mappedBy ) ) {
|
||||||
/*
|
/*
|
||||||
* we need to check if the columns are in the right order
|
* we need to check if the columns are in the right order
|
||||||
|
|
|
@ -522,7 +522,7 @@ public abstract class CollectionBinder {
|
||||||
binder.setProperty( property );
|
binder.setProperty( property );
|
||||||
binder.setInsertable( insertable );
|
binder.setInsertable( insertable );
|
||||||
binder.setUpdatable( updatable );
|
binder.setUpdatable( updatable );
|
||||||
Property prop = binder.make();
|
Property prop = binder.makeProperty();
|
||||||
//we don't care about the join stuffs because the column is on the association table.
|
//we don't care about the join stuffs because the column is on the association table.
|
||||||
if (! declaringClassSet) throw new AssertionFailure( "DeclaringClass is not set in CollectionBinder while binding" );
|
if (! declaringClassSet) throw new AssertionFailure( "DeclaringClass is not set in CollectionBinder while binding" );
|
||||||
propertyHolder.addProperty( prop, declaringClass );
|
propertyHolder.addProperty( prop, declaringClass );
|
||||||
|
|
|
@ -23,29 +23,35 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.cfg.annotations;
|
package org.hibernate.cfg.annotations;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import javax.persistence.EmbeddedId;
|
import javax.persistence.EmbeddedId;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.annotations.Generated;
|
import org.hibernate.annotations.Generated;
|
||||||
import org.hibernate.annotations.GenerationTime;
|
import org.hibernate.annotations.GenerationTime;
|
||||||
import org.hibernate.annotations.Immutable;
|
import org.hibernate.annotations.Immutable;
|
||||||
import org.hibernate.annotations.NaturalId;
|
import org.hibernate.annotations.NaturalId;
|
||||||
import org.hibernate.annotations.OptimisticLock;
|
import org.hibernate.annotations.OptimisticLock;
|
||||||
|
import org.hibernate.annotations.common.AssertionFailure;
|
||||||
import org.hibernate.annotations.common.reflection.XClass;
|
import org.hibernate.annotations.common.reflection.XClass;
|
||||||
import org.hibernate.annotations.common.reflection.XProperty;
|
import org.hibernate.annotations.common.reflection.XProperty;
|
||||||
import org.hibernate.annotations.common.AssertionFailure;
|
|
||||||
import org.hibernate.cfg.AccessType;
|
import org.hibernate.cfg.AccessType;
|
||||||
|
import org.hibernate.cfg.BinderHelper;
|
||||||
import org.hibernate.cfg.Ejb3Column;
|
import org.hibernate.cfg.Ejb3Column;
|
||||||
import org.hibernate.cfg.ExtendedMappings;
|
import org.hibernate.cfg.ExtendedMappings;
|
||||||
|
import org.hibernate.cfg.InheritanceState;
|
||||||
import org.hibernate.cfg.PropertyHolder;
|
import org.hibernate.cfg.PropertyHolder;
|
||||||
|
import org.hibernate.mapping.KeyValue;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.PropertyGeneration;
|
import org.hibernate.mapping.PropertyGeneration;
|
||||||
|
import org.hibernate.mapping.RootClass;
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.mapping.Value;
|
import org.hibernate.mapping.Value;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
|
@ -66,6 +72,11 @@ public class PropertyBinder {
|
||||||
private SimpleValueBinder simpleValueBinder;
|
private SimpleValueBinder simpleValueBinder;
|
||||||
private XClass declaringClass;
|
private XClass declaringClass;
|
||||||
private boolean declaringClassSet;
|
private boolean declaringClassSet;
|
||||||
|
private boolean embedded;
|
||||||
|
|
||||||
|
public void setEmbedded(boolean embedded) {
|
||||||
|
this.embedded = embedded;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* property can be null
|
* property can be null
|
||||||
|
@ -73,6 +84,9 @@ public class PropertyBinder {
|
||||||
*/
|
*/
|
||||||
private XProperty property;
|
private XProperty property;
|
||||||
private XClass returnedClass;
|
private XClass returnedClass;
|
||||||
|
private boolean isId;
|
||||||
|
private Map<XClass, InheritanceState> inheritanceStatePerClass;
|
||||||
|
private Property mappingProperty;
|
||||||
|
|
||||||
public void setInsertable(boolean insertable) {
|
public void setInsertable(boolean insertable) {
|
||||||
this.insertable = insertable;
|
this.insertable = insertable;
|
||||||
|
@ -82,7 +96,6 @@ public class PropertyBinder {
|
||||||
this.updatable = updatable;
|
this.updatable = updatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
@ -129,8 +142,10 @@ public class PropertyBinder {
|
||||||
|
|
||||||
private void validateBind() {
|
private void validateBind() {
|
||||||
if ( property.isAnnotationPresent( Immutable.class ) ) {
|
if ( property.isAnnotationPresent( Immutable.class ) ) {
|
||||||
throw new AnnotationException("@Immutable on property not allowed. " +
|
throw new AnnotationException(
|
||||||
"Only allowed on entity level or on a collection.");
|
"@Immutable on property not allowed. " +
|
||||||
|
"Only allowed on entity level or on a collection."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if ( !declaringClassSet ) {
|
if ( !declaringClassSet ) {
|
||||||
throw new AssertionFailure( "declaringClass has not been set before a bind" );
|
throw new AssertionFailure( "declaringClass has not been set before a bind" );
|
||||||
|
@ -141,7 +156,7 @@ public class PropertyBinder {
|
||||||
//TODO check necessary params for a make
|
//TODO check necessary params for a make
|
||||||
}
|
}
|
||||||
|
|
||||||
public Property bind() {
|
private Property makePropertyAndValue() {
|
||||||
validateBind();
|
validateBind();
|
||||||
log.debug( "binding property {} with lazy={}", name, lazy );
|
log.debug( "binding property {} with lazy={}", name, lazy );
|
||||||
String containerClassName = holder == null ?
|
String containerClassName = holder == null ?
|
||||||
|
@ -157,12 +172,51 @@ public class PropertyBinder {
|
||||||
simpleValueBinder.setMappings( mappings );
|
simpleValueBinder.setMappings( mappings );
|
||||||
SimpleValue propertyValue = simpleValueBinder.make();
|
SimpleValue propertyValue = simpleValueBinder.make();
|
||||||
setValue( propertyValue );
|
setValue( propertyValue );
|
||||||
Property prop = make();
|
return makeProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
//used when value is provided
|
||||||
|
public Property makePropertyAndBind() {
|
||||||
|
return bind( makeProperty() );
|
||||||
|
}
|
||||||
|
|
||||||
|
//used to build everything from scratch
|
||||||
|
public Property makePropertyValueAndBind() {
|
||||||
|
return bind( makePropertyAndValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Property bind(Property prop) {
|
||||||
|
if (isId) {
|
||||||
|
final RootClass rootClass = ( RootClass ) holder.getPersistentClass();
|
||||||
|
rootClass.setIdentifier( ( KeyValue ) getValue() );
|
||||||
|
|
||||||
|
if (embedded) {
|
||||||
|
rootClass.setEmbeddedIdentifier( true );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rootClass.setIdentifierProperty( prop );
|
||||||
|
final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(
|
||||||
|
declaringClass,
|
||||||
|
inheritanceStatePerClass,
|
||||||
|
mappings
|
||||||
|
);
|
||||||
|
if (superclass != null) {
|
||||||
|
superclass.setDeclaredIdentifierProperty(prop);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//we know the property is on the actual entity
|
||||||
|
rootClass.setDeclaredIdentifierProperty( prop );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
holder.addProperty( prop, columns, declaringClass );
|
holder.addProperty( prop, columns, declaringClass );
|
||||||
|
}
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Property make() {
|
//used when the value is provided and the binding is done elsewhere
|
||||||
|
public Property makeProperty() {
|
||||||
validateMake();
|
validateMake();
|
||||||
log.debug( "Building property " + name );
|
log.debug( "Building property " + name );
|
||||||
Property prop = new Property();
|
Property prop = new Property();
|
||||||
|
@ -182,8 +236,10 @@ public class PropertyBinder {
|
||||||
if ( !GenerationTime.NEVER.equals( generated ) ) {
|
if ( !GenerationTime.NEVER.equals( generated ) ) {
|
||||||
if ( property.isAnnotationPresent( javax.persistence.Version.class )
|
if ( property.isAnnotationPresent( javax.persistence.Version.class )
|
||||||
&& GenerationTime.INSERT.equals( generated ) ) {
|
&& GenerationTime.INSERT.equals( generated ) ) {
|
||||||
throw new AnnotationException( "@Generated(INSERT) on a @Version property not allowed, use ALWAYS: "
|
throw new AnnotationException(
|
||||||
+ StringHelper.qualify( holder.getPath(), name ) );
|
"@Generated(INSERT) on a @Version property not allowed, use ALWAYS: "
|
||||||
|
+ StringHelper.qualify( holder.getPath(), name )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
insertable = false;
|
insertable = false;
|
||||||
if ( GenerationTime.ALWAYS.equals( generated ) ) {
|
if ( GenerationTime.ALWAYS.equals( generated ) ) {
|
||||||
|
@ -213,11 +269,14 @@ public class PropertyBinder {
|
||||||
property.isAnnotationPresent( javax.persistence.Version.class )
|
property.isAnnotationPresent( javax.persistence.Version.class )
|
||||||
|| property.isAnnotationPresent( Id.class )
|
|| property.isAnnotationPresent( Id.class )
|
||||||
|| property.isAnnotationPresent( EmbeddedId.class ) ) ) {
|
|| property.isAnnotationPresent( EmbeddedId.class ) ) ) {
|
||||||
throw new AnnotationException( "@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version: "
|
throw new AnnotationException(
|
||||||
+ StringHelper.qualify( holder.getPath(), name ) );
|
"@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version: "
|
||||||
|
+ StringHelper.qualify( holder.getPath(), name )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.trace( "Cascading " + name + " with " + cascade );
|
log.trace( "Cascading " + name + " with " + cascade );
|
||||||
|
this.mappingProperty = prop;
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,4 +292,15 @@ public class PropertyBinder {
|
||||||
return simpleValueBinder;
|
return simpleValueBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Value getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(boolean id) {
|
||||||
|
this.isId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInheritanceStatePerClass(Map<XClass, InheritanceState> inheritanceStatePerClass) {
|
||||||
|
this.inheritanceStatePerClass = inheritanceStatePerClass;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.hibernate.test.util.SchemaUtil;
|
||||||
/**
|
/**
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
public class DerivedIdentitySimpleParentSimpleDepTest extends TestCase {
|
public class DerivedIdentitySimpleParentSimpleDepMapsIdTest extends TestCase {
|
||||||
|
|
||||||
public void testOneToOneExplicitJoinColumn() throws Exception {
|
public void testOneToOneExplicitJoinColumn() throws Exception {
|
||||||
assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", getCfg() ) );
|
assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", getCfg() ) );
|
Loading…
Reference in New Issue