HHH-6354 component attribute natural id binding

This commit is contained in:
Strong Liu 2012-06-27 17:29:54 +08:00
parent 473790c1e4
commit 1ab72cfdb6
9 changed files with 74 additions and 76 deletions

View File

@ -171,21 +171,22 @@ public class Binder {
private final MetadataImplementor metadata;
private final IdentifierGeneratorFactory identifierGeneratorFactory;
private final ObjectNameNormalizer nameNormalizer;
private final HashMap< String, EntitySource > entitySourcesByName = new HashMap< String, EntitySource >();
private final HashMap< RootEntitySource, EntityHierarchy > entityHierarchiesByRootEntitySource =
new HashMap< RootEntitySource, EntityHierarchy >();
private final HashMap< String, AttributeSource > attributeSourcesByName = new HashMap< String, AttributeSource >();
private final LinkedList< LocalBindingContext > bindingContexts = new LinkedList< LocalBindingContext >();
private final LinkedList< InheritanceType > inheritanceTypes = new LinkedList< InheritanceType >();
private final HashMap<String, EntitySource> entitySourcesByName = new HashMap<String, EntitySource>();
private final HashMap<RootEntitySource, EntityHierarchy> entityHierarchiesByRootEntitySource =
new HashMap<RootEntitySource, EntityHierarchy>();
private final HashMap<String, AttributeSource> attributeSourcesByName = new HashMap<String, AttributeSource>();
private final LinkedList<LocalBindingContext> bindingContexts = new LinkedList<LocalBindingContext>();
private final LinkedList<InheritanceType> inheritanceTypes = new LinkedList<InheritanceType>();
private final LinkedList< EntityMode > entityModes = new LinkedList< EntityMode >();
private final LinkedList<EntityMode> entityModes = new LinkedList<EntityMode>();
private final HibernateTypeHelper typeHelper; // todo: refactor helper and remove redundant methods in this class
public Binder( final MetadataImplementor metadata, final IdentifierGeneratorFactory identifierGeneratorFactory ) {
this.metadata = metadata;
this.identifierGeneratorFactory = identifierGeneratorFactory;
nameNormalizer = new ObjectNameNormalizer() {
this.typeHelper = new HibernateTypeHelper( this, metadata );
this.nameNormalizer = new ObjectNameNormalizer() {
@Override
protected NamingStrategy getNamingStrategy() {
@ -197,13 +198,12 @@ public class Binder {
return metadata.isGloballyQuotedIdentifiers();
}
};
typeHelper = new HibernateTypeHelper( this, metadata );
}
private AttributeBinding attributeBinding( final String entityName, final String attributeName ) {
// Check if binding has already been created
EntityBinding entityBinding = entityBinding( entityName );
AttributeSource attributeSource = attributeSourcesByName.get( attributeSourcesByNameKey( entityName, attributeName ) );
final EntityBinding entityBinding = entityBinding( entityName );
final AttributeSource attributeSource = attributeSourcesByName.get( attributeSourcesByNameKey( entityName, attributeName ) );
bindAttribute( entityBinding, attributeSource );
return entityBinding.locateAttributeBinding( attributeName );
}
@ -250,13 +250,13 @@ public class Binder {
case MANY_TO_ONE:
return bindManyToOneAttribute(
attributeBindingContainer,
(ToOneAttributeSource) attributeSource,
ToOneAttributeSource.class.cast( attributeSource ),
attribute
);
case COMPONENT:
return bindComponentAttribute(
attributeBindingContainer,
(ComponentAttributeSource) attributeSource,
ComponentAttributeSource.class.cast( attributeSource ),
attribute
);
default:
@ -303,16 +303,14 @@ public class Binder {
final AttributeBindingContainer attributeBindingContainer,
final ComponentAttributeSource attributeSource,
SingularAttribute attribute ) {
Composite composite;
final Composite composite;
if ( attribute == null ) {
composite =
new Composite(
composite = new Composite(
attributeSource.getPath(),
attributeSource.getClassName(),
attributeSource.getClassReference(),
null );
attribute =
attributeBindingContainer.getAttributeContainer().createCompositeAttribute(
attribute = attributeBindingContainer.getAttributeContainer().createCompositeAttribute(
attributeSource.getName(),
composite );
} else {
@ -325,6 +323,7 @@ public class Binder {
} else {
referencingAttribute = composite.createSingularAttribute( attributeSource.getParentReferenceAttributeName() );
}
final SingularAttributeBinding.NaturalIdMutability naturalIdMutability = attributeSource.getNaturalIdMutability();
final CompositeAttributeBinding attributeBinding =
attributeBindingContainer.makeComponentAttributeBinding(
attribute,
@ -332,7 +331,7 @@ public class Binder {
propertyAccessorName( attributeSource ),
attributeSource.isIncludedInOptimisticLocking(),
attributeSource.isLazy(),
attributeSource.getNaturalIdMutability(),
naturalIdMutability,
createMetaAttributeContext( attributeBindingContainer, attributeSource ) );
bindAttributes( attributeBinding, attributeSource );
return attributeBinding;
@ -346,7 +345,7 @@ public class Binder {
attribute = createSingularAttribute( attributeBindingContainer, attributeSource );
}
// TODO: figure out which table is used (could be secondary table...)
TableSpecification table = attributeBindingContainer.seekEntityBinding().getPrimaryTable();
final TableSpecification table = attributeBindingContainer.seekEntityBinding().getPrimaryTable();
final List< RelationalValueBinding > relationalValueBindings =
bindValues( attributeBindingContainer, attributeSource, attribute, table );
@ -936,7 +935,6 @@ public class Binder {
bindingContexts.peek().getMappingDefaults().getDiscriminatorColumnName(),
false,
false,
false,
false );
} else {
value = table.locateOrCreateDerivedValue( ( ( DerivedValueSource ) valueSource ).getExpression() );
@ -995,7 +993,6 @@ public class Binder {
bindingContexts.peek().getMappingDefaults().getDiscriminatorColumnName(),
false,
false,
false,
false
);
}
@ -1459,7 +1456,7 @@ public class Binder {
private void bindUniqueConstraints( final EntityBinding entityBinding, final EntitySource entitySource ) {
for ( final ConstraintSource constraintSource : entitySource.getConstraints() ) {
if ( constraintSource instanceof UniqueConstraintSource ) {
if ( UniqueConstraintSource.class.isInstance( constraintSource ) ) {
final TableSpecification table = entityBinding.locateTable( constraintSource.getTableName() );
final String constraintName = constraintSource.name();
if ( constraintName == null ) {
@ -1484,14 +1481,17 @@ public class Binder {
) ? SingularAttributeSource.class.cast( valueSourceContainer ).getNaturalIdMutability()
: SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
final boolean isNaturalId = naturalIdMutability != SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
final boolean isImmutable = isNaturalId && (naturalIdMutability == SingularAttributeBinding.NaturalIdMutability.IMMUTABLE);
final boolean isImmutableNaturalId = isNaturalId && (naturalIdMutability == SingularAttributeBinding.NaturalIdMutability.IMMUTABLE);
if ( valueSourceContainer.relationalValueSources().isEmpty() ) {
final String columnName =
quotedIdentifier( bindingContexts.peek().getNamingStrategy().propertyToColumnName( attribute.getName() ) );
final Column column = defaultTable.locateOrCreateColumn( columnName );
column.setNullable( !isNaturalId && valueSourceContainer.areValuesNullableByDefault() );
column.setUnique( isNaturalId );
valueBindings.add( new RelationalValueBinding( column, true, !isImmutable ) );
if(isNaturalId){
addUniqueConstraintForNaturalIdColumn( defaultTable, column );
}
valueBindings.add( new RelationalValueBinding( column, true, !isImmutableNaturalId ) );
} else {
final String name = attribute.getName();
for ( final RelationalValueSource valueSource : valueSourceContainer.relationalValueSources() ) {
@ -1509,15 +1509,11 @@ public class Binder {
toBoolean(
columnSource.isIncludedInUpdate(),
valueSourceContainer.areValuesIncludedInUpdateByDefault() );
valueBindings.add( new RelationalValueBinding( createColumn(
table,
columnSource,
name,
isNaturalId,
isNaturalId,
valueSourceContainer.areValuesNullableByDefault(),
true ), isIncludedInInsert, !isImmutable && isIncludedInUpdate ) );
Column column = createColumn( table, columnSource, name, isNaturalId, valueSourceContainer.areValuesNullableByDefault(), true );
if(isNaturalId){
addUniqueConstraintForNaturalIdColumn( table, column );
}
valueBindings.add( new RelationalValueBinding( column, isIncludedInInsert, !isImmutableNaturalId && isIncludedInUpdate ) );
} else {
final DerivedValue derivedValue =
table.locateOrCreateDerivedValue( ( ( DerivedValueSource ) valueSource ).getExpression() );
@ -1528,6 +1524,11 @@ public class Binder {
return valueBindings;
}
private void addUniqueConstraintForNaturalIdColumn(final TableSpecification table, final Column column) {
final UniqueKey uniqueKey = table.getOrCreateUniqueKey( "natural_id_unique_key_" );
uniqueKey.addColumn( column );
}
private void bindVersion( final EntityBinding rootEntityBinding, final VersionAttributeSource versionAttributeSource ) {
if ( versionAttributeSource == null ) {
return;
@ -1575,7 +1576,6 @@ public class Binder {
final ColumnSource columnSource,
final String defaultName,
final boolean forceNotNull,
final boolean forceUnique,
final boolean isNullableByDefault,
final boolean isDefaultAttributeName ) {
if ( columnSource.getName() == null && defaultName == null ) {
@ -1608,7 +1608,7 @@ public class Binder {
column.setJdbcDataType( columnSource.getDatatype() );
column.setReadFragment( columnSource.getReadFragment() );
column.setWriteFragment( columnSource.getWriteFragment() );
column.setUnique( forceUnique || columnSource.isUnique() );
column.setUnique( columnSource.isUnique() );
column.setCheckCondition( columnSource.getCheckCondition() );
column.setComment( columnSource.getComment() );
return column;

View File

@ -85,7 +85,7 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
/**
* Is this property a natural id property and what's the mutability it is.
*/
private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
private SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
/**
* Whether a change of the property's value triggers a version increment of the entity (in case of optimistic
@ -164,6 +164,10 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
return naturalIdMutability;
}
public void setNaturalIdMutability(SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
this.naturalIdMutability = naturalIdMutability;
}
public AttributeNature getAttributeNature() {
return attributeNature;
}
@ -281,6 +285,8 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
}
return checkCondition;
}
}

View File

@ -122,9 +122,11 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
if ( attributeOverrides.containsKey( tmp ) ) {
attributeOverride = attributeOverrides.get( tmp );
}
attribute.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() );
attributeList.add( new SingularAttributeSourceImpl( attribute, attributeOverride ) );
}
for ( EmbeddableClass embeddable : embeddableClass.getEmbeddedClasses().values() ) {
embeddable.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() );
attributeList.add(
new ComponentAttributeSourceImpl(
embeddable,
@ -134,6 +136,7 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
);
}
for ( AssociationAttribute associationAttribute : embeddableClass.getAssociationAttributes() ) {
associationAttribute.setNaturalIdMutability( embeddableClass.getNaturalIdMutability() );
attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) );
}
return Collections.unmodifiableList( attributeList );

View File

@ -41,7 +41,7 @@ import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
public class EmbeddableClass extends ConfiguredClass {
private final String embeddedAttributeName;
private final String parentReferencingAttributeName;
private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
private SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
public EmbeddableClass(
ClassInfo classInfo,
@ -75,6 +75,10 @@ public class EmbeddableClass extends ConfiguredClass {
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return naturalIdMutability;
}
public void setNaturalIdMutability(SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
this.naturalIdMutability = naturalIdMutability;
}
}

View File

@ -67,8 +67,7 @@ public class EntityBindingContext implements LocalBindingContext, AnnotationBind
public EntityBindingContext(AnnotationBindingContext contextDelegate, ConfiguredClass source) {
this.contextDelegate = contextDelegate;
this.origin = new Origin( SourceType.ANNOTATION, source.getName() );
localIdentifierGeneratorDefinitionMap = processLocalIdentifierGeneratorDefinitions( source.getClassInfo() );
this.localIdentifierGeneratorDefinitionMap = processLocalIdentifierGeneratorDefinitions( source.getClassInfo() );
}
private Map<String,IdGenerator> processLocalIdentifierGeneratorDefinitions(final ClassInfo classInfo) {
@ -217,7 +216,7 @@ public class EntityBindingContext implements LocalBindingContext, AnnotationBind
public IdGenerator findIdGenerator(String name) {
IdGenerator definition = localIdentifierGeneratorDefinitionMap.get( name );
if ( definition == null ) {
contextDelegate.findIdGenerator( name );
definition= contextDelegate.findIdGenerator( name );
}
return definition;
}

View File

@ -131,17 +131,13 @@ public class EntityClass extends ConfiguredClass {
super( classInfo, hierarchyAccessType, parent, context );
this.inheritanceType = inheritanceType;
this.idType = determineIdType();
boolean hasOwnTable = definesItsOwnTable();
final boolean hasOwnTable = definesItsOwnTable();
this.explicitEntityName = determineExplicitEntityName();
this.constraintSources = new HashSet<ConstraintSource>();
if ( hasOwnTable ) {
this.primaryTableSource = createPrimaryTableSource();
}
else {
this.primaryTableSource = null;
}
this.primaryTableSource = hasOwnTable ? createPrimaryTableSource() : null;
this.secondaryTableSources = createSecondaryTableSources();
this.customLoaderQueryName = determineCustomLoader();
@ -213,12 +209,7 @@ public class EntityClass extends ConfiguredClass {
public TableSpecificationSource getPrimaryTableSource() {
// todo : this is different from hbm which returns null if "!definesItsOwnTable()"
if ( definesItsOwnTable() ) {
return primaryTableSource;
}
else {
return ( (EntityClass) getParent() ).getPrimaryTableSource();
}
return definesItsOwnTable() ? primaryTableSource : ( (EntityClass) getParent() ).getPrimaryTableSource();
}
public Set<SecondaryTableSource> getSecondaryTableSources() {
@ -669,16 +660,16 @@ public class EntityClass extends ConfiguredClass {
}
private void createUniqueConstraints(AnnotationInstance tableAnnotation, String tableName) {
AnnotationValue value = tableAnnotation.value( "uniqueConstraints" );
final AnnotationValue value = tableAnnotation.value( "uniqueConstraints" );
if ( value == null ) {
return;
}
AnnotationInstance[] uniqueConstraints = value.asNestedArray();
for ( AnnotationInstance unique : uniqueConstraints ) {
String name = unique.value( "name" ) == null ? null : unique.value( "name" ).asString();
String[] columnNames = unique.value( "columnNames" ).asStringArray();
UniqueConstraintSourceImpl uniqueConstraintSource =
final AnnotationInstance[] uniqueConstraints = value.asNestedArray();
for ( final AnnotationInstance unique : uniqueConstraints ) {
final String name = unique.value( "name" ) == null ? null : unique.value( "name" ).asString();
final String[] columnNames = unique.value( "columnNames" ).asStringArray();
final UniqueConstraintSourceImpl uniqueConstraintSource =
new UniqueConstraintSourceImpl(
name, tableName, Arrays.asList( columnNames )
);
@ -827,12 +818,7 @@ public class EntityClass extends ConfiguredClass {
|| hibernateProxyAnnotation.value( "lazy" ).asBoolean();
if ( isLazy ) {
final AnnotationValue proxyClassValue = hibernateProxyAnnotation.value( "proxyClass" );
if ( proxyClassValue == null ) {
proxy = getName();
}
else {
proxy = proxyClassValue.asString();
}
proxy = proxyClassValue == null? getName() : proxyClassValue.asString();
}
else {
proxy = null;

View File

@ -193,12 +193,12 @@ public class CompositeAttributeBinding
@Override
public AttributeBinding locateAttributeBinding(List<org.hibernate.metamodel.spi.relational.Value> values) {
for(AttributeBinding attributeBinding : attributeBindingMap.values()) {
if(!(attributeBinding instanceof BasicAttributeBinding)) {
for ( final AttributeBinding attributeBinding : attributeBindingMap.values() ) {
if ( !BasicAttributeBinding.class.isInstance( attributeBinding ) ) {
continue;
}
BasicAttributeBinding basicAttributeBinding = (BasicAttributeBinding) attributeBinding;
if(basicAttributeBinding.getRelationalValueBindings().equals( values )) {
final BasicAttributeBinding basicAttributeBinding = (BasicAttributeBinding) attributeBinding;
if ( basicAttributeBinding.getRelationalValueBindings().equals( values ) ) {
return attributeBinding;
}
}

View File

@ -43,7 +43,7 @@ public class RelationalValueBinding {
private final boolean isDerived;
private final boolean isNullable;
public RelationalValueBinding(DerivedValue value) {
public RelationalValueBinding(final DerivedValue value) {
this.value = value;
this.includeInInsert = false;
this.includeInUpdate = false;
@ -51,7 +51,7 @@ public class RelationalValueBinding {
this.isNullable = true;
}
public RelationalValueBinding(Column value, boolean includeInInsert, boolean includeInUpdate) {
public RelationalValueBinding(final Column value, final boolean includeInInsert, final boolean includeInUpdate) {
this.value = value;
this.includeInInsert = includeInInsert;
this.includeInUpdate = includeInUpdate;

View File

@ -44,7 +44,7 @@ public class Building {
private Integer id;
private String name;
@NaturalId
private String address;
@NaturalId
@ -138,5 +138,5 @@ public class Building {
return "Building [id=" + id + ", name=" + name + ", address=" + address + ", city=" + city + ", state=" + state
+ "]";
}
}