Skip to content

Commit

Permalink
HHH-8879 HHH-8994 : Embeddable with associations used as a Map key
Browse files Browse the repository at this point in the history
  • Loading branch information
gbadner committed Mar 27, 2015
1 parent 5d365cf commit 64c3e4c
Show file tree
Hide file tree
Showing 10 changed files with 363 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package org.hibernate.loader.plan.build.internal.returns;

import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.build.internal.spaces.CompositePropertyMapping;
import org.hibernate.loader.plan.build.internal.spaces.QuerySpaceHelper;
Expand All @@ -34,6 +35,7 @@
import org.hibernate.loader.plan.spi.CollectionReference;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.CollectionPropertyNames;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.type.CompositeType;
Expand All @@ -50,20 +52,41 @@ public abstract class AbstractCollectionReference implements CollectionReference
private final CollectionFetchableIndex index;
private final CollectionFetchableElement element;

private final boolean allowElementJoin;
private final boolean allowIndexJoin;

protected AbstractCollectionReference(
ExpandingCollectionQuerySpace collectionQuerySpace,
PropertyPath propertyPath,
boolean shouldIncludeJoins) {
this.collectionQuerySpace = collectionQuerySpace;
this.propertyPath = propertyPath;

this.index = buildIndexGraph( collectionQuerySpace, shouldIncludeJoins );
this.element = buildElementGraph( collectionQuerySpace, shouldIncludeJoins );
this.allowElementJoin = shouldIncludeJoins;

// Currently we can only allow a join for the collection index if all of the following are true:
// - collection element joins are allowed;
// - index is an EntityType;
// - index values are not "formulas" (e.g., a @MapKey index is translated into "formula" value(s)).
// Hibernate cannot currently support eager joining of associations within a component (@Embeddable) as an index.
if ( shouldIncludeJoins &&
collectionQuerySpace.getCollectionPersister().hasIndex() &&
collectionQuerySpace.getCollectionPersister().getIndexType().isEntityType() ) {
final String[] indexFormulas =
( (QueryableCollection) collectionQuerySpace.getCollectionPersister() ).getIndexFormulas();
final int nNonNullFormulas = ArrayHelper.countNonNull( indexFormulas );
this.allowIndexJoin = nNonNullFormulas == 0;
}
else {
this.allowIndexJoin = false;
}

// All other fields must be initialized before building this.index and this.element.
this.index = buildIndexGraph();
this.element = buildElementGraph();
}

private CollectionFetchableIndex buildIndexGraph(
ExpandingCollectionQuerySpace collectionQuerySpace,
boolean shouldIncludeJoins) {
private CollectionFetchableIndex buildIndexGraph() {
final CollectionPersister persister = collectionQuerySpace.getCollectionPersister();
if ( persister.hasIndex() ) {
final Type type = persister.getIndexType();
Expand All @@ -80,7 +103,7 @@ private CollectionFetchableIndex buildIndexGraph(
(EntityType) persister.getIndexType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
shouldIncludeJoins
allowIndexJoin
);
return new CollectionFetchableIndexEntityGraph( this, entityQuerySpace );
}
Expand All @@ -100,7 +123,7 @@ else if ( type.isComponentType() ) {
(CompositeType) persister.getIndexType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
shouldIncludeJoins
allowIndexJoin
);
return new CollectionFetchableIndexCompositeGraph( this, compositeQuerySpace );
}
Expand All @@ -109,9 +132,7 @@ else if ( type.isComponentType() ) {
return null;
}

private CollectionFetchableElement buildElementGraph(
ExpandingCollectionQuerySpace collectionQuerySpace,
boolean shouldIncludeJoins) {
private CollectionFetchableElement buildElementGraph() {
final CollectionPersister persister = collectionQuerySpace.getCollectionPersister();
final Type type = persister.getElementType();
if ( type.isAssociationType() ) {
Expand All @@ -126,7 +147,7 @@ private CollectionFetchableElement buildElementGraph(
(EntityType) persister.getElementType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
shouldIncludeJoins
allowElementJoin
);
return new CollectionFetchableElementEntityGraph( this, entityQuerySpace );
}
Expand All @@ -146,14 +167,24 @@ else if ( type.isComponentType() ) {
(CompositeType) persister.getElementType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
shouldIncludeJoins
allowElementJoin
);
return new CollectionFetchableElementCompositeGraph( this, compositeQuerySpace );
}

return null;
}

@Override
public boolean allowElementJoin() {
return allowElementJoin;
}

@Override
public boolean allowIndexJoin() {
return allowIndexJoin;
}

@Override
public String getQuerySpaceUid() {
return collectionQuerySpace.getUid();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,13 @@ protected AbstractCollectionLoadQueryDetails(
new CollectionReturnReader( rootReturn ),
new CollectionReferenceInitializerImpl( rootReturn, collectionReferenceAliases )
);
if ( rootReturn.getCollectionPersister().getElementType().isEntityType() ) {
if ( rootReturn.allowElementJoin() && rootReturn.getCollectionPersister().getElementType().isEntityType() ) {
final EntityReference elementEntityReference = rootReturn.getElementGraph().resolveEntityReference();
readerCollector.add(
new EntityReferenceInitializerImpl( elementEntityReference, collectionReferenceAliases.getEntityElementAliases() )
);
}
if ( rootReturn.getCollectionPersister().hasIndex() &&
rootReturn.getCollectionPersister().getIndexType().isEntityType() ) {
if ( rootReturn.allowIndexJoin() && rootReturn.getCollectionPersister().getIndexType().isEntityType() ) {
final EntityReference indexEntityReference = rootReturn.getIndexGraph().resolveEntityReference();
final EntityReferenceAliases indexEntityReferenceAliases = aliasResolutionContext.generateEntityReferenceAliases(
indexEntityReference.getQuerySpaceUid(),
Expand Down Expand Up @@ -134,8 +133,7 @@ protected boolean shouldApplyRootReturnFilterBeforeKeyRestriction() {

@Override
protected void applyRootReturnSelectFragments(SelectStatementBuilder selectStatementBuilder) {
if ( getQueryableCollection().hasIndex() &&
getQueryableCollection().getIndexType().isEntityType() ) {
if ( getRootCollectionReturn().allowIndexJoin() && getQueryableCollection().getIndexType().isEntityType() ) {
final EntityReference indexEntityReference = getRootCollectionReturn().getIndexGraph().resolveEntityReference();
final EntityReferenceAliases indexEntityReferenceAliases = getAliasResolutionContext().resolveEntityReferenceAliases(
indexEntityReference.getQuerySpaceUid()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,20 @@ public interface CollectionReference {
* @return The PropertyPath
*/
public PropertyPath getPropertyPath();

/**
* Should a collection element join be allowed? Returning <code>true</code>
* indicates that an element join can safely be added.
*
* @return true, if a collection index join is allowed.
*/
public boolean allowElementJoin();

/**
* Should a collection index join be allowed? Returning <code>true</code>
* indicates that an index join can safely be added.
*
* @return true, if a collection index join is allowed.
*/
public boolean allowIndexJoin();
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public static Iterable<AttributeDefinition> getCompositeCollectionIndexSubAttrib
(OuterJoinLoadable) collectionPersister.getOwnerEntityPersister(),
(CompositeType) collectionPersister.getIndexType(),
collectionPersister.getTableName(),
collectionPersister.getIndexColumnNames()
collectionPersister.toColumns( "index" )
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ private void visitAttributes(AttributeSource attributeSource) {
if ( attributeDefinitions == null ) {
return;
}
for ( AttributeDefinition attributeDefinition : attributeSource.getAttributes() ) {
for ( AttributeDefinition attributeDefinition : attributeDefinitions ) {
visitAttributeDefinition( attributeDefinition );
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//$Id$
package org.hibernate.test.annotations.indexcoll;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;


@Entity
public class Currency {
private Integer id;


@Id
@GeneratedValue
public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}


@Column
private String currency;


public String getCurrency() {
return currency;
}

public void setCurrency(String currency) {
this.currency = currency;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//$Id$
package org.hibernate.test.annotations.indexcoll;
import java.math.BigDecimal;
import java.util.Map;

import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import org.hibernate.annotations.CascadeType;


@Entity
public class ExchangeOffice {
public ExchangeOffice() {
super();
}

@Id @GeneratedValue
private Integer id;


public void setId(Integer id) {
this.id = id;
}


public Integer getId() {
return id;
}

@javax.persistence.OneToMany(mappedBy = "parent")
@javax.persistence.MapKey(name="key")
private Map<ExchangeRateKey, ExchangeRate> exchangeRates = new java.util.HashMap<ExchangeRateKey, ExchangeRate>();

public Map<ExchangeRateKey,ExchangeRate> getExchangeRates() {
return exchangeRates;
}

@ElementCollection
private Map<ExchangeRateKey, BigDecimal> exchangeRateFees = new java.util.HashMap<ExchangeRateKey, BigDecimal>();

public Map<ExchangeRateKey,BigDecimal> getExchangeRateFees() {
return exchangeRateFees;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//$Id$
package org.hibernate.test.annotations.indexcoll;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;


@Entity
public class ExchangeRate {
public ExchangeRate() {
super();
}

@Id @GeneratedValue
private Integer id;

@Column
private double rate;



public double getRate() {
return rate;
}

public void setRate(double rate) {
this.rate = rate;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

@Embedded
private ExchangeRateKey key = new ExchangeRateKey();

public ExchangeRateKey getKey() {
return key;
}

public void setKey(ExchangeRateKey key) {
this.key = key;
}

@javax.persistence.ManyToOne(fetch = FetchType.LAZY )
private ExchangeOffice parent = null;


public ExchangeOffice getParent() {
return parent;
}

public void setParent(ExchangeOffice parent) {
this.parent = parent;
}
}
Loading

0 comments on commit 64c3e4c

Please sign in to comment.