HHH-6354 component attribute natural id binding
This commit is contained in:
parent
473790c1e4
commit
1ab72cfdb6
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
+ "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue