Skip to content

Commit

Permalink
HHH-7240 - Develop identifier handling in new metamodel
Browse files Browse the repository at this point in the history
  • Loading branch information
sebersole committed Apr 13, 2012
1 parent a39b1a3 commit 5946391
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 45 deletions.
Expand Up @@ -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;

Expand All @@ -42,17 +44,15 @@
public class EntityIdentifier {
private final EntityBinding entityBinding;

private BoundType boundType;
private List<SingularAttributeBinding> identifierAttributeBindings = new ArrayList<SingularAttributeBinding>();

private IdGenerator idGenerator;
private String unsavedValue;

private Class idClassClass; // the class named in @IdClass

private IdentifierGenerator identifierGenerator;

private SingularNonAssociationAttributeBinding attributeBinding;
private List<SingularAttributeBinding> nonAggregatedCompositeAttributeBindings;
private int columnCount;

/**
* Create an identifier
Expand All @@ -67,71 +67,112 @@ public void bindAsSingleAttributeIdentifier(
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() ) {
entityBinding.getPrimaryTable().getPrimaryKey().addColumn( (Column) valueBinding.getValue() );
}
}

private void ensureNotBound() {
if ( ! identifierAttributeBindings.isEmpty() ) {
throw new IllegalStateException( "Entity identifier was already bound" );
}
}

public void bindAsMultipleAttributeIdentifier(
List<SingularAttributeBinding> 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<SingularAttributeBinding> getIdentifierAttributeBindings() {
return Collections.unmodifiableList( identifierAttributeBindings );
}

public List<SingularAttributeBinding> getNonAggregatedCompositeAttributeBindings() {
return nonAggregatedCompositeAttributeBindings;
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() {
return unsavedValue;
}

public boolean isEmbedded() {
return boundType == BoundType.SINGLE_ATTRIBUTE && attributeBinding.getRelationalValueBindings().size() > 1;
return isSingleAttribute() && columnCount > 1;
}

public Class getIdClassClass() {
return idClassClass;
}

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;
}
}
Expand Up @@ -775,14 +775,11 @@ public 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();
Expand All @@ -791,24 +788,20 @@ public 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() ) {
Expand Down Expand Up @@ -882,7 +875,7 @@ public 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;
}
Expand Down Expand Up @@ -985,7 +978,7 @@ public AbstractEntityPersister(
List<Boolean> propNullables = new ArrayList<Boolean>();

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;
}
Expand Down
Expand Up @@ -619,7 +619,7 @@ else if ( entityBinding.getDiscriminatorMatchValue().equals( NOT_NULL_STRING ) )
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() ) {
Expand Down
Expand Up @@ -426,7 +426,7 @@ public EntityMetamodel(EntityBinding entityBinding, SessionFactoryImplementor se
boolean foundUpdateableNaturalIdProperty = false;

for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) {
if ( attributeBinding == rootEntityIdentifier ) {
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
// skip the identifier attribute binding
continue;
}
Expand Down

0 comments on commit 5946391

Please sign in to comment.