From e55c1bb47ee8224174ecb21740f04f5c27d99230 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Thu, 7 Feb 2013 19:49:15 -0800 Subject: [PATCH] HHH-7830 : union-subclass support --- .../hibernate/metamodel/internal/Binder.java | 201 +++++------------- .../JoinedSubclassEntitySourceImpl.java | 7 + ...oManyPluralAttributeElementSourceImpl.java | 6 + .../PluralAttributeKeySourceImpl.java | 6 + .../annotations/SecondaryTableSourceImpl.java | 7 + .../annotations/ToOneAttributeSourceImpl.java | 10 + .../hbm/AbstractToOneAttributeSourceImpl.java | 5 + .../hbm/JoinedSubclassEntitySourceImpl.java | 6 + ...oManyPluralAttributeElementSourceImpl.java | 6 + .../hbm/PluralAttributeKeySourceImpl.java | 5 + .../source/hbm/SecondaryTableSourceImpl.java | 5 + .../AbstractTableSpecification.java | 62 ++++-- .../spi/relational/AbstractValue.java | 9 +- .../metamodel/spi/relational/Column.java | 30 +-- .../spi/relational/DenormalizedTable.java | 9 - .../spi/relational/DerivedValue.java | 11 +- .../metamodel/spi/relational/Value.java | 12 +- .../source/ForeignKeyContributingSource.java | 17 ++ 18 files changed, 222 insertions(+), 192 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java index 4f21074368..3126a09fbc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java @@ -685,7 +685,7 @@ public class Binder { quotedIdentifier( secondaryTableSource.getExplicitForeignKeyName() ), table, joinRelationalValueBindings, - determineForeignKeyTargetTable( entityBinding, targetColumns ), + determineForeignKeyTargetTable( entityBinding, secondaryTableSource ), targetColumns ); SecondaryTable secondaryTable = new SecondaryTable( table, foreignKey ); @@ -1205,7 +1205,7 @@ public class Binder { quotedIdentifier( attributeSource.getExplicitForeignKeyName() ), attributeBinding.getRelationalValueBindings().get( 0 ).getTable(), attributeBinding.getRelationalValueBindings(), - determineForeignKeyTargetTable( attributeBinding.getReferencedEntityBinding(), targetColumns ), + determineForeignKeyTargetTable( attributeBinding.getReferencedEntityBinding(), attributeSource ), targetColumns ); } @@ -1328,7 +1328,7 @@ public class Binder { quotedIdentifier( attributeSource.getExplicitForeignKeyName() ), foreignKeyRelationalValueBindings.get( 0 ).getTable(), foreignKeyRelationalValueBindings, - determineForeignKeyTargetTable( attributeBinding.getReferencedEntityBinding(), targetColumns ), + determineForeignKeyTargetTable( attributeBinding.getReferencedEntityBinding(), attributeSource ), targetColumns ); } @@ -1896,7 +1896,7 @@ public class Binder { quotedIdentifier( elementSource.getExplicitForeignKeyName() ), collectionTable, elementBinding.getRelationalValueBindings(), - determineForeignKeyTargetTable( referencedEntityBinding, targetColumns ), + determineForeignKeyTargetTable( referencedEntityBinding, elementSource ), targetColumns ); } @@ -2196,44 +2196,13 @@ public class Binder { final String referencedAttributeName = resolutionDelegate.getReferencedAttributeName(); if ( referencedAttributeName == null ) { referencedAttributeBinding = attributeBindingContainer.locateAttributeBinding( - resolutionDelegate.getJoinColumns( - new JoinColumnResolutionContext() { - @Override - public List resolveRelationalValuesForAttribute(String attributeName) { - return null; - } - - @Override - public Column resolveColumn(String logicalColumnName, String logicalTableName, String logicalSchemaName, String logicalCatalogName) { - for ( AttributeBinding attributeBinding : attributeBindingContainer.attributeBindings() ) { - if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) { - SingularAttributeBinding singularAttributeBinding = SingularAttributeBinding.class - .cast( - attributeBinding - ); - for ( RelationalValueBinding relationalValueBinding : singularAttributeBinding - .getRelationalValueBindings() ) { - if ( Column.class.isInstance( relationalValueBinding.getValue() ) ) { - Identifier columnIdentifier = createIdentifier( logicalColumnName); - Column column = Column.class.cast( relationalValueBinding.getValue() ); - if ( column.getColumnName().equals( columnIdentifier ) ) { - return column; - } - } - } - } - } - return null; - } - } - ) + resolutionDelegate.getJoinColumns( new JoinColumnResolutionContextImpl( entityBinding ) ) ); } else { referencedAttributeBinding = attributeBindingContainer.locateAttributeBinding( referencedAttributeName ); } - if ( referencedAttributeBinding == null ) { referencedAttributeBinding = attributeBinding( entityBinding.getEntity().getName(), @@ -2402,7 +2371,7 @@ public class Binder { quotedIdentifier( keySource.getExplicitForeignKeyName() ), collectionTable, sourceRelationalBindings, - determineForeignKeyTargetTable( attributeBinding.getContainer().seekEntityBinding(), targetColumns ), + determineForeignKeyTargetTable( attributeBinding.getContainer().seekEntityBinding(), keySource ), targetColumns ); foreignKey.setDeleteRule( keySource.getOnDeleteAction() ); @@ -2539,7 +2508,7 @@ public class Binder { quotedIdentifier( subclassEntitySource.getExplicitForeignKeyName() ), entityBinding.getPrimaryTable(), sourceColumns, - determineForeignKeyTargetTable( superEntityBinding, targetColumns ), + determineForeignKeyTargetTable( superEntityBinding, subclassEntitySource ), targetColumns ); @@ -2851,60 +2820,7 @@ public class Binder { } else { final List columns = new ArrayList(); - final JoinColumnResolutionContext resolutionContext = - new JoinColumnResolutionContext() { - @Override - public Column resolveColumn( - String logicalColumnName, - String logicalTableName, - String logicalSchemaName, - String logicalCatalogName) { - // ignore table, schema, catalog name - Column column = entityBinding.getPrimaryTable().locateColumn( logicalColumnName ); - if ( column == null ) { - column = entityBinding.getPrimaryTable().createColumn( logicalColumnName ); - } - return column; - } - - @Override - public List resolveRelationalValuesForAttribute(String attributeName) { - if ( attributeName == null ) { - List values = new ArrayList(); - for ( Column column : entityBinding.getPrimaryTable().getPrimaryKey().getColumns() ) { - values.add( column ); - } - return values; - } - final AttributeBinding referencedAttributeBinding = - entityBinding.locateAttributeBindingByPath( attributeName, true ); - if ( referencedAttributeBinding == null ) { - throw bindingContext().makeMappingException( - String.format( - "Could not resolve named referenced property [%s] against entity [%s]", - attributeName, - entityBinding.getEntity().getName() - ) - ); - } - if ( !referencedAttributeBinding.getAttribute().isSingular() ) { - throw bindingContext().makeMappingException( - String.format( - "Referenced property [%s] against entity [%s] is a plural attribute; it must be a singular attribute.", - attributeName, - entityBinding.getEntity().getName() - ) - ); - } - List valueBindings = - ( (SingularAttributeBinding) referencedAttributeBinding ).getRelationalValueBindings(); - List values = new ArrayList( valueBindings.size() ); - for ( RelationalValueBinding valueBinding : valueBindings ) { - values.add( valueBinding.getValue() ); - } - return values; - } - }; + final JoinColumnResolutionContext resolutionContext = new JoinColumnResolutionContextImpl( entityBinding ); for ( Value relationalValue : fkColumnResolutionDelegate.getJoinColumns( resolutionContext ) ) { if ( !Column.class.isInstance( relationalValue ) ) { throw bindingContext().makeMappingException( @@ -2917,41 +2833,19 @@ public class Binder { } } - private TableSpecification determineForeignKeyTargetTable(final EntityBinding entityBinding, - final List targetColumns) { - TableSpecification table = null; - TableSpecification actualTable = null; - boolean first = true; - for ( Column column : targetColumns) { - if ( first ) { - table = column.getTable(); - if ( entityBinding.hasTable( table.getLogicalName().getText() ) ) { - actualTable = table; - } - else { - if ( entityBinding.getHierarchyDetails().getInheritanceType() == InheritanceType.TABLE_PER_CLASS && - column == entityBinding.getPrimaryTable().locateColumn( column.getColumnName().getText() ) ) { - actualTable = entityBinding.getPrimaryTable(); - } - else { - throw bindingContext().makeMappingException( "improve this message!!!" ); - } - } - first = false; - } - else { - if ( !table.equals( column.getTable() ) ) { - throw bindingContext().makeMappingException( - String.format( - "Join columns come from more than one table: %s, %s ", - table, - column.getTable() - ) - ); - } - } + private TableSpecification determineForeignKeyTargetTable( + final EntityBinding entityBinding, + final ForeignKeyContributingSource foreignKeyContributingSource) { + + final JoinColumnResolutionDelegate fkColumnResolutionDelegate = + foreignKeyContributingSource.getForeignKeyTargetColumnResolutionDelegate(); + if ( fkColumnResolutionDelegate == null ) { + return entityBinding.getPrimaryTable(); + } + else { + final JoinColumnResolutionContext resolutionContext = new JoinColumnResolutionContextImpl( entityBinding ); + return fkColumnResolutionDelegate.getReferencedTable( resolutionContext ); } - return actualTable; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ simple instance helper methods @@ -3274,19 +3168,23 @@ public class Binder { String logicalTableName, String logicalSchemaName, String logicalCatalogName) { + if ( bindingContext().isGloballyQuotedIdentifiers() && !StringHelper.isQuoted( logicalColumnName ) ) { + logicalColumnName = StringHelper.quote( logicalColumnName ); + } + return resolveTable( logicalTableName, logicalSchemaName, logicalCatalogName ).locateOrCreateColumn( + logicalColumnName + ); + } + + @Override + public TableSpecification resolveTable(String logicalTableName, String logicalSchemaName, String logicalCatalogName) { Identifier tableIdentifier = createIdentifier( logicalTableName ); if ( tableIdentifier == null ) { tableIdentifier = referencedEntityBinding.getPrimaryTable().getLogicalName(); } Schema schema = metadata.getDatabase().getSchema( logicalCatalogName, logicalSchemaName ); - Table table = schema.locateTable( tableIdentifier ); - - if ( bindingContext().isGloballyQuotedIdentifiers() && !StringHelper.isQuoted( logicalColumnName ) ) { - logicalColumnName = StringHelper.quote( logicalColumnName ); - } - - return table.locateColumn( logicalColumnName ); + return schema.locateTable( tableIdentifier ); } @Override @@ -3298,12 +3196,35 @@ public class Binder { } return values; } + List valueBindings = + resolveReferencedAttributeBinding( attributeName ).getRelationalValueBindings(); + List values = new ArrayList( valueBindings.size() ); + for ( RelationalValueBinding valueBinding : valueBindings ) { + values.add( valueBinding.getValue() ); + } + return values; + } + + @Override + public TableSpecification resolveTableForAttribute(String attributeName) { + if ( attributeName == null ) { + return referencedEntityBinding.getPrimaryTable(); + } + else { + return resolveReferencedAttributeBinding( attributeName ).getRelationalValueBindings().get( 0 ).getTable(); + } + } + + private SingularAttributeBinding resolveReferencedAttributeBinding(String attributeName) { + if ( attributeName == null ) { + return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); + } final AttributeBinding referencedAttributeBinding = - referencedEntityBinding.locateAttributeBinding( attributeName ); + referencedEntityBinding.locateAttributeBindingByPath( attributeName, true ); if ( referencedAttributeBinding == null ) { throw bindingContext().makeMappingException( String.format( - "Could not resolve named property-ref [%s] against entity [%s]", + "Could not resolve named referenced property [%s] against entity [%s]", attributeName, referencedEntityBinding.getEntity().getName() ) @@ -3312,19 +3233,13 @@ public class Binder { if ( !referencedAttributeBinding.getAttribute().isSingular() ) { throw bindingContext().makeMappingException( String.format( - "Property-ref [%s] against entity [%s] is a plural attribute; it must be a singular attribute.", + "Referenced property [%s] against entity [%s] is a plural attribute; it must be a singular attribute.", attributeName, referencedEntityBinding.getEntity().getName() ) ); } - List values = new ArrayList(); - SingularAttributeBinding referencedAttributeBindingAsSingular = - (SingularAttributeBinding) referencedAttributeBinding; - for ( RelationalValueBinding valueBinding : referencedAttributeBindingAsSingular.getRelationalValueBindings() ) { - values.add( valueBinding.getValue() ); - } - return values; + return (SingularAttributeBinding) referencedAttributeBinding; } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JoinedSubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JoinedSubclassEntitySourceImpl.java index 2a0073383b..f1d5f09d92 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JoinedSubclassEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/JoinedSubclassEntitySourceImpl.java @@ -30,9 +30,11 @@ import org.hibernate.annotations.OnDeleteAction; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.metamodel.internal.source.annotations.attribute.PrimaryKeyJoinColumn; import org.hibernate.metamodel.internal.source.annotations.entity.EntityClass; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.ColumnSource; import org.hibernate.metamodel.spi.source.EntitySource; +import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; import org.hibernate.metamodel.spi.source.JoinedSubclassEntitySource; /** @@ -102,6 +104,11 @@ public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl imp return columns; } + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( null, null, null ); + } + @Override public String getReferencedAttributeName() { return null; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyPluralAttributeElementSourceImpl.java index 8497f01235..a5c3273285 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyPluralAttributeElementSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ManyToManyPluralAttributeElementSourceImpl.java @@ -34,6 +34,7 @@ import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssoc import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper; import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.FilterSource; import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; @@ -188,6 +189,11 @@ public class ManyToManyPluralAttributeElementSourceImpl implements ManyToManyPlu return values; } + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( logicalJoinTableName, null, null ); + } + @Override public String getReferencedAttributeName() { // HBM only diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java index ca62225e8b..3beaefb1e2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/PluralAttributeKeySourceImpl.java @@ -32,6 +32,7 @@ import org.hibernate.internal.util.StringHelper; import org.hibernate.metamodel.internal.source.annotations.attribute.Column; import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute; import org.hibernate.metamodel.spi.relational.ForeignKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.PluralAttributeKeySource; import org.hibernate.metamodel.spi.source.RelationalValueSource; @@ -122,5 +123,10 @@ public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource { public String getReferencedAttributeName() { return null; } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( null ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SecondaryTableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SecondaryTableSourceImpl.java index 87448ee97d..e634de9dfe 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SecondaryTableSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/SecondaryTableSourceImpl.java @@ -28,8 +28,10 @@ import java.util.List; import org.hibernate.engine.FetchStyle; import org.hibernate.metamodel.internal.source.annotations.attribute.PrimaryKeyJoinColumn; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; import org.hibernate.metamodel.spi.source.SecondaryTableSource; import org.hibernate.metamodel.spi.source.TableSpecificationSource; @@ -130,6 +132,11 @@ public class SecondaryTableSourceImpl implements SecondaryTableSource { return columns; } + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( null, null, null ); + } + @Override public String getReferencedAttributeName() { return null; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneAttributeSourceImpl.java index 6b5231702f..63ce36b363 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/ToOneAttributeSourceImpl.java @@ -43,6 +43,7 @@ import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; import org.hibernate.metamodel.spi.source.RelationalValueSource; @@ -217,6 +218,15 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem return values; } + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTable( + logicalJoinTableName, + null, + null + ); + } + @Override public String getReferencedAttributeName() { // in annotations we are not referencing attribute but column names via @JoinColumn(s) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java index 7270205361..9813527f0a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java @@ -224,6 +224,11 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource public List getJoinColumns(JoinColumnResolutionContext context) { return context.resolveRelationalValuesForAttribute( propertyRef ); } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( propertyRef ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/JoinedSubclassEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/JoinedSubclassEntitySourceImpl.java index d55e34fdac..9be2bb1b77 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/JoinedSubclassEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/JoinedSubclassEntitySourceImpl.java @@ -30,6 +30,7 @@ import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; import org.hibernate.jaxb.spi.hbm.JaxbJoinedSubclassElement; import org.hibernate.jaxb.spi.hbm.JaxbKeyElement; import org.hibernate.jaxb.spi.hbm.JaxbOnDeleteAttribute; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.ColumnSource; import org.hibernate.metamodel.spi.source.EntitySource; @@ -103,6 +104,11 @@ public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl imp return context.resolveRelationalValuesForAttribute( key.getPropertyRef() ); } + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( key.getPropertyRef() ); + } + @Override public String getReferencedAttributeName() { return key.getPropertyRef(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java index 63eb4df639..99aefea9d7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToManyPluralAttributeElementSourceImpl.java @@ -33,6 +33,7 @@ import org.hibernate.jaxb.spi.hbm.JaxbClassElement; import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; import org.hibernate.jaxb.spi.hbm.JaxbFilterElement; import org.hibernate.jaxb.spi.hbm.JaxbManyToManyElement; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.FilterSource; import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource; @@ -223,6 +224,11 @@ public class ManyToManyPluralAttributeElementSourceImpl public List getJoinColumns(JoinColumnResolutionContext context) { return context.resolveRelationalValuesForAttribute( manyToManyElement.getPropertyRef() ); } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( manyToManyElement.getPropertyRef() ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/PluralAttributeKeySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/PluralAttributeKeySourceImpl.java index 15cc8cdb58..6befc00709 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/PluralAttributeKeySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/PluralAttributeKeySourceImpl.java @@ -102,6 +102,11 @@ public class PluralAttributeKeySourceImpl public String getReferencedAttributeName() { return keyElement.getPropertyRef(); } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( keyElement.getPropertyRef() ); + } }; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SecondaryTableSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SecondaryTableSourceImpl.java index 9827346f96..e458436d28 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SecondaryTableSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/SecondaryTableSourceImpl.java @@ -168,5 +168,10 @@ class SecondaryTableSourceImpl extends AbstractHbmSourceNode implements Secondar public String getReferencedAttributeName() { return joinElement.getKey().getPropertyRef(); } + + @Override + public TableSpecification getReferencedTable(JoinColumnResolutionContext context) { + return context.resolveTableForAttribute( joinElement.getKey().getPropertyRef() ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java index 9a6abae8a2..e7176097db 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java @@ -36,10 +36,46 @@ import java.util.List; * @author Brett Meyer */ public abstract class AbstractTableSpecification implements TableSpecification { + + // A column an derived value can have the same text, so use the Value.ValueType to disambiguate. + private class ValueKey { + private final Value.ValueType valueType; + private final Identifier identifier; + + private ValueKey(Value.ValueType valueType, Identifier identifier) { + this.valueType = valueType; + this.identifier = identifier; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + ValueKey valueKey = (ValueKey) o; + + if ( identifier != null ? !identifier.equals( valueKey.identifier ) : valueKey.identifier != null ) { + return false; + } + return valueType == valueKey.valueType; + + } + + @Override + public int hashCode() { + int result = valueType != null ? valueType.hashCode() : 0; + result = 31 * result + ( identifier != null ? identifier.hashCode() : 0 ); + return result; + } + } private int tableNumber; private final List valueList = new ArrayList(); - private final LinkedHashMap valueMap = new LinkedHashMap(); + private final LinkedHashMap valueMap = new LinkedHashMap(); private final PrimaryKey primaryKey = new PrimaryKey( this ); private final List foreignKeys = new ArrayList(); @@ -72,8 +108,9 @@ public abstract class AbstractTableSpecification implements TableSpecification { @Override public Column locateColumn(String name) { final Identifier identifier = Identifier.toIdentifier( name ); - if ( valueMap.containsKey( identifier ) ) { - Value value = valueMap.get( identifier ); + final ValueKey valueKey = new ValueKey( Value.ValueType.COLUMN, identifier ); + if ( valueMap.containsKey( valueKey ) ) { + Value value = valueMap.get( valueKey ); return Column.class.isInstance( value ) ? Column.class.cast( value ) : null; } return null; @@ -91,8 +128,8 @@ public abstract class AbstractTableSpecification implements TableSpecification { @Override public Column createColumn(Identifier name) { - final Column column = new Column( this, valueList.size(), name ); - valueMap.put( name, column ); + final Column column = new Column( valueList.size(), name ); + valueMap.put( new ValueKey( column.getValueType(), name ), column ); valueList.add( column ); return column; } @@ -105,8 +142,9 @@ public abstract class AbstractTableSpecification implements TableSpecification { protected DerivedValue locateDerivedValue(String fragment) { final Identifier identifier = Identifier.toIdentifier( fragment ); - if ( valueMap.containsKey( identifier ) ) { - Value value = valueMap.get( identifier ); + final ValueKey valueKey = new ValueKey( Value.ValueType.DERIVED_VALUE, identifier ); + if ( valueMap.containsKey( valueKey ) ) { + Value value = valueMap.get( valueKey ); if ( DerivedValue.class.isInstance( value ) ) { return DerivedValue.class.cast( value ); } @@ -116,8 +154,8 @@ public abstract class AbstractTableSpecification implements TableSpecification { protected DerivedValue createDerivedValue(String fragment) { final Identifier identifier = Identifier.toIdentifier( fragment ); - final DerivedValue value = new DerivedValue( this, valueList.size(), fragment ); - valueMap.put( identifier, value ); + final DerivedValue value = new DerivedValue( valueList.size(), fragment ); + valueMap.put( new ValueKey( value.getValueType(), identifier ), value ); valueList.add( value ); return value; } @@ -180,9 +218,9 @@ public abstract class AbstractTableSpecification implements TableSpecification { return result; } - protected void sameTableCheck(Column column) { - if ( !this.equals( column.getTable() ) ) { + private void sameTableCheck(Column column) { + if ( ! hasValue( column ) ) { throw new IllegalArgumentException( "All columns must be from this table." ); } } -} +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java index 07059e0549..db5e20f021 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java @@ -37,20 +37,13 @@ public abstract class AbstractValue implements Value { private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AbstractValue.class.getName()); - private final TableSpecification table; private final int position; private JdbcDataType jdbcDataType; - protected AbstractValue(TableSpecification table, int position) { - this.table = table; + protected AbstractValue(int position) { this.position = position; } - @Override - public TableSpecification getTable() { - return table; - } - public int getPosition() { return position; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java index a797703e50..9113c2a521 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java @@ -54,12 +54,8 @@ public class Column extends AbstractValue { private boolean isIdentity = false; - protected Column(TableSpecification table, int position, String name) { - this( table, position, Identifier.toIdentifier( name ) ); - } - - protected Column(TableSpecification table, int position, Identifier name) { - super( table, position ); + protected Column(int position, Identifier name) { + super( position ); this.columnName = name; } @@ -174,9 +170,14 @@ public class Column extends AbstractValue { this.isIdentity = isIdentity; } + @Override + public ValueType getValueType() { + return ValueType.COLUMN; + } + @Override public String toLoggableString() { - return getTable().getLoggableValueQualifier() + '.' + getColumnName(); + return getColumnName().getText(); } // TODO: this is fairly complicated logic. It would be more straightforward @@ -232,20 +233,21 @@ public class Column extends AbstractValue { if ( this == o ) { return true; } - if ( ! ( o instanceof Column ) ) { + if ( o == null || getClass() != o.getClass() ) { return false; } - final Column that = (Column) o; + Column column = (Column) o; - return EqualsHelper.equals( this.columnName, that.columnName ) - && EqualsHelper.equals( this.getTable(), that.getTable() ); + if ( columnName != null ? !columnName.equals( column.columnName ) : column.columnName != null ) { + return false; + } + + return true; } @Override public int hashCode() { - int result = columnName != null ? columnName.hashCode() : 0; - result = 31 * result + ( getTable() != null ? getTable().hashCode() : 0 ); - return result; + return columnName != null ? columnName.hashCode() : 0; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java index 781caae61e..f7dede09bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DenormalizedTable.java @@ -125,13 +125,4 @@ public class DenormalizedTable extends Table { public PrimaryKey getPrimaryKey() { return includedTable.getPrimaryKey(); } - - @Override - protected void sameTableCheck(Column column) { - try{ - super.sameTableCheck( column ); - } catch ( IllegalArgumentException e ){ - includedTable.sameTableCheck( column ); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java index e5cda7a4ea..c743958fd8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java @@ -33,16 +33,21 @@ import org.hibernate.dialect.Dialect; public class DerivedValue extends AbstractValue { private final String expression; - public DerivedValue(TableSpecification table, int position, String expression) { - super( table, position ); + public DerivedValue(int position, String expression) { + super( position ); this.expression = expression; } + @Override + public ValueType getValueType() { + return ValueType.DERIVED_VALUE; + } + /** * {@inheritDoc} */ public String toLoggableString() { - return getTable().toLoggableString() + ".{derived-column}"; + return "{derived-column}"; } /** diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java index fe814cef5c..0c41d56b1b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java @@ -32,12 +32,18 @@ import org.hibernate.dialect.Dialect; * @author Steve Ebersole */ public interface Value { + + public enum ValueType { + COLUMN, + DERIVED_VALUE + } + /** - * Retrieve the table that owns this value. + * Return the value type. * - * @return The owning table. + * @return The value type */ - public TableSpecification getTable(); + public ValueType getValueType(); /** * Retrieve the JDBC data type of this value. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ForeignKeyContributingSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ForeignKeyContributingSource.java index b3787a1dc3..b05b0b5576 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ForeignKeyContributingSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ForeignKeyContributingSource.java @@ -26,6 +26,7 @@ package org.hibernate.metamodel.spi.source; import java.util.List; import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.relational.Value; /** @@ -67,6 +68,8 @@ public interface ForeignKeyContributingSource { */ public List getJoinColumns(JoinColumnResolutionContext context); + public TableSpecification getReferencedTable(JoinColumnResolutionContext context); + /** * Retrieves the explicitly named attribute that maps to the non-PK foreign-key target columns. * @@ -89,6 +92,8 @@ public interface ForeignKeyContributingSource { */ public List resolveRelationalValuesForAttribute(String attributeName); + public TableSpecification resolveTableForAttribute(String attributeName); + /** * Resolve a column reference given the logical names of both the table and the column. Used in the * {@link javax.persistence.JoinColumn} case @@ -101,5 +106,17 @@ public interface ForeignKeyContributingSource { * @return The column. */ public Column resolveColumn(String logicalColumnName, String logicalTableName, String logicalSchemaName, String logicalCatalogName); + + /** + * Resolve a table reference given the logical names of the table and the column. Used in the + * {@link javax.persistence.JoinColumn} case + * + * @param logicalTableName The logical table name. + * @param logicalSchemaName The logical schema name. + * @param logicalCatalogName The logical catalog name. + * + * @return The column. + */ + public TableSpecification resolveTable(String logicalTableName, String logicalSchemaName, String logicalCatalogName); } }