From 594639147751a5abe872b84333f7c841df0e9631 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Thu, 12 Apr 2012 12:11:23 -0500 Subject: [PATCH] HHH-7240 - Develop identifier handling in new metamodel --- .../spi/binding/EntityIdentifier.java | 91 ++++++++++++++----- .../entity/AbstractEntityPersister.java | 29 +++--- .../entity/SingleTableEntityPersister.java | 2 +- .../tuple/entity/EntityMetamodel.java | 2 +- 4 files changed, 79 insertions(+), 45 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java index 5eb1cd323d..ac5aa8f00c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java @@ -23,6 +23,8 @@ */ package org.hibernate.metamodel.spi.binding; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Properties; @@ -42,7 +44,7 @@ import org.hibernate.metamodel.spi.relational.Column; public class EntityIdentifier { private final EntityBinding entityBinding; - private BoundType boundType; + private List identifierAttributeBindings = new ArrayList(); private IdGenerator idGenerator; private String unsavedValue; @@ -50,9 +52,7 @@ public class EntityIdentifier { private Class idClassClass; // the class named in @IdClass private IdentifierGenerator identifierGenerator; - - private SingularNonAssociationAttributeBinding attributeBinding; - private List nonAggregatedCompositeAttributeBindings; + private int columnCount; /** * Create an identifier @@ -67,13 +67,11 @@ public class EntityIdentifier { SingularNonAssociationAttributeBinding attributeBinding, IdGenerator idGenerator, String unsavedValue) { - if ( boundType != null ) { - throw new IllegalStateException( "Entity identifier was already bound" ); - } - this.boundType = BoundType.SINGLE_ATTRIBUTE; - this.attributeBinding = attributeBinding; + ensureNotBound(); + identifierAttributeBindings.add( attributeBinding ); this.idGenerator = idGenerator; this.unsavedValue = unsavedValue; + this.columnCount = attributeBinding.getRelationalValueBindings().size(); // Configure primary key in relational model for ( final RelationalValueBinding valueBinding : attributeBinding.getRelationalValueBindings() ) { @@ -81,23 +79,52 @@ public class EntityIdentifier { } } + private void ensureNotBound() { + if ( ! identifierAttributeBindings.isEmpty() ) { + throw new IllegalStateException( "Entity identifier was already bound" ); + } + } + public void bindAsMultipleAttributeIdentifier( List nonAggregatedCompositeAttributeBindings, Class idClassClass) { - if ( boundType != null ) { - throw new IllegalStateException( "Entity identifier was already bound" ); + ensureNotBound(); + for ( SingularAttributeBinding attributeBinding : nonAggregatedCompositeAttributeBindings ) { + identifierAttributeBindings.add( attributeBinding ); + columnCount += attributeBinding.getRelationalValueBindings().size(); + + // Configure primary key in relational model + for ( final RelationalValueBinding valueBinding : attributeBinding.getRelationalValueBindings() ) { + entityBinding.getPrimaryTable().getPrimaryKey().addColumn( (Column) valueBinding.getValue() ); + } } - this.boundType = BoundType.MULTIPLE_ATTRIBUTE; - this.nonAggregatedCompositeAttributeBindings = nonAggregatedCompositeAttributeBindings; this.idClassClass = idClassClass; } - public SingularNonAssociationAttributeBinding getValueBinding() { - return attributeBinding; + public boolean isSingleAttribute() { + ensureBound(); + return identifierAttributeBindings.size() == 1; } - public List getNonAggregatedCompositeAttributeBindings() { - return nonAggregatedCompositeAttributeBindings; + public List getIdentifierAttributeBindings() { + return Collections.unmodifiableList( identifierAttributeBindings ); + } + + public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) { + for ( SingularAttributeBinding identifierAttributeBinding : identifierAttributeBindings ) { + if ( identifierAttributeBinding.equals( attributeBinding ) ) { + return true; + } + } + return false; + } + + protected SingularNonAssociationAttributeBinding getSingleIdentifierAttributeBinding() { + if ( ! isSingleAttribute() ) { + throw new IllegalStateException( "Entity identifier is made up of multiple attributes" ); + } + + return (SingularNonAssociationAttributeBinding) identifierAttributeBindings.get( 0 ); } public String getUnsavedValue() { @@ -105,7 +132,7 @@ public class EntityIdentifier { } public boolean isEmbedded() { - return boundType == BoundType.SINGLE_ATTRIBUTE && attributeBinding.getRelationalValueBindings().size() > 1; + return isSingleAttribute() && columnCount > 1; } public Class getIdClassClass() { @@ -113,25 +140,39 @@ public class EntityIdentifier { } public boolean isIdentifierMapper() { - // i think - return boundType == BoundType.MULTIPLE_ATTRIBUTE && idClassClass != null; + // i think this is the intended check for this method + return ! isSingleAttribute() && idClassClass != null; } // todo do we really need this createIdentifierGenerator and how do we make sure the getter is not called too early // maybe some sort of visitor pattern here!? (HF) public IdentifierGenerator createIdentifierGenerator(IdentifierGeneratorFactory factory, Properties properties) { - if ( idGenerator != null ) { - identifierGenerator = attributeBinding.createIdentifierGenerator( idGenerator, factory, properties ); + ensureBound(); + if ( identifierGenerator == null ) { + if ( isSingleAttribute() && idGenerator != null ) { + identifierGenerator = getSingleIdentifierAttributeBinding().createIdentifierGenerator( + idGenerator, + factory, + properties + ); + } } return identifierGenerator; } public IdentifierGenerator getIdentifierGenerator() { + ensureBound(); return identifierGenerator; } - private static enum BoundType { - SINGLE_ATTRIBUTE, - MULTIPLE_ATTRIBUTE + protected void ensureBound() { + if ( identifierAttributeBindings.isEmpty() ) { + throw new IllegalStateException( "Entity identifier was not yet bound" ); + } + } + + public int getColumnCount() { + ensureBound(); + return columnCount; } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 0762810600..3be2198a32 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -775,14 +775,11 @@ public abstract class AbstractEntityPersister final SessionFactoryImplementor factory) throws HibernateException { this.factory = factory; this.cacheAccessStrategy = cacheAccessStrategy; - this.isLazyPropertiesCacheable = - entityBinding.getHierarchyDetails().getCaching() == null ? - false : - entityBinding.getHierarchyDetails().getCaching().isCacheLazyProperties(); - this.cacheEntryStructure = - factory.getSettings().isStructuredCacheEntriesEnabled() ? - new StructuredCacheEntry(this) : - new UnstructuredCacheEntry(); + this.isLazyPropertiesCacheable = entityBinding.getHierarchyDetails().getCaching() != null + && entityBinding.getHierarchyDetails().getCaching().isCacheLazyProperties(); + this.cacheEntryStructure = factory.getSettings().isStructuredCacheEntriesEnabled() + ? new StructuredCacheEntry(this) + : new UnstructuredCacheEntry(); this.entityMetamodel = new EntityMetamodel( entityBinding, factory ); this.entityTuplizer = this.entityMetamodel.getTuplizer(); int batch = entityBinding.getBatchSize(); @@ -791,24 +788,20 @@ public abstract class AbstractEntityPersister } batchSize = batch; hasSubselectLoadableCollections = entityBinding.hasSubselectLoadableCollections(); + rowIdName = entityBinding.getRowId(); + loaderName = entityBinding.getCustomLoaderName(); propertyMapping = new BasicEntityPropertyMapping( this ); + // IDENTIFIER - identifierColumnSpan = entityBinding.getHierarchyDetails() - .getEntityIdentifier() - .getValueBinding() - .getRelationalValueBindings() - .size(); + identifierColumnSpan = entityBinding.getHierarchyDetails().getEntityIdentifier().getColumnCount(); rootTableKeyColumnNames = new String[identifierColumnSpan]; rootTableKeyColumnReaders = new String[identifierColumnSpan]; rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan]; identifierAliases = new String[identifierColumnSpan]; - rowIdName = entityBinding.getRowId(); - - loaderName = entityBinding.getCustomLoaderName(); int i = 0; for ( org.hibernate.metamodel.spi.relational.Column col : entityBinding.getPrimaryTable().getPrimaryKey().getColumns() ) { @@ -882,7 +875,7 @@ public abstract class AbstractEntityPersister i = 0; boolean foundFormula = false; for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { - if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { + if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) { // entity identifier is not considered a "normal" property continue; } @@ -985,7 +978,7 @@ public abstract class AbstractEntityPersister List propNullables = new ArrayList(); for ( AttributeBinding attributeBinding : entityBinding.getSubEntityAttributeBindingClosure() ) { - if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { + if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) { // entity identifier is not considered a "normal" property continue; } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index ee6339035c..9dbe7f3f2e 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -619,7 +619,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { for( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { // TODO: fix when joins are working (HHH-6391) //propertyTableNumbers[i++] = entityBinding.getJoinNumber( attributeBinding); - if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { + if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) { continue; // skip identifier binding } if ( ! attributeBinding.getAttribute().isSingular() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java index e1d21efb27..db1ea9df7b 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java @@ -426,7 +426,7 @@ public class EntityMetamodel implements Serializable { boolean foundUpdateableNaturalIdProperty = false; for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { - if ( attributeBinding == rootEntityIdentifier ) { + if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) { // skip the identifier attribute binding continue; }