initial work on circular fetch detection across embeddables
This commit is contained in:
parent
8c806a5a16
commit
4f750cdc55
|
@ -26,4 +26,9 @@ public interface AttributeMapping extends ModelPart, ValueMapping {
|
|||
ManagedMappingType getDeclaringType();
|
||||
|
||||
PropertyAccess getPropertyAccess();
|
||||
|
||||
@Override
|
||||
default EntityMappingType findContainingEntityMapping() {
|
||||
return getDeclaringType().findContainingEntityMapping();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import java.util.Iterator;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -26,16 +25,17 @@ import org.hibernate.mapping.Property;
|
|||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
|
||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
||||
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
@ -220,6 +220,11 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
return getEmbeddedValueMapping().getPartName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return valueMapping.getNavigableRole();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DomainResult<T> createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
|
@ -332,6 +337,11 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return valueMapping.findContainingEntityMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfAttributeMappings() {
|
||||
return attributeMappings.size();
|
||||
|
|
|
@ -8,9 +8,9 @@ package org.hibernate.metamodel.mapping;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
|
||||
|
|
|
@ -54,6 +54,11 @@ public interface EntityMappingType extends ManagedMappingType, Loadable {
|
|||
|
||||
String getEntityName();
|
||||
|
||||
@Override
|
||||
default EntityMappingType findContainingEntityMapping() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
default String getPartName() {
|
||||
return getEntityName();
|
||||
|
|
|
@ -9,6 +9,8 @@ package org.hibernate.metamodel.mapping;
|
|||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
|
@ -33,6 +35,34 @@ public interface ModelPart extends MappingModelExpressable {
|
|||
|
||||
String getPartName();
|
||||
|
||||
/**
|
||||
* @asciidoc
|
||||
*
|
||||
* The path for this fetchable back to an entity in the domain model.
|
||||
*
|
||||
* Some examples:
|
||||
*
|
||||
* For an entity, the role name is simply the entity name.
|
||||
*
|
||||
* For embeddable the role name is the path back to the root entity. E.g. a Person's address
|
||||
* would be a path `Person#address`.
|
||||
*
|
||||
* For a collection the path would be the same as the "collection role". E.g. an Order's lineItems
|
||||
* would be `Order#lineItems`. This is the same as the historical `CollectionPersister#getRoleName`.
|
||||
*
|
||||
* For the (model)parts of a collection the role is either `{element}` or `{index}` depending. E.g.
|
||||
* `Order#lineItems.{element}`. Attributes of the element or index type (embeddable or entity typed)
|
||||
* would be based on this role. E.g. `Order#lineItems.{element}.quantity`
|
||||
*
|
||||
* For an attribute of an embedded, the role would be relative to its "container". E.g. `Person#address.city` or
|
||||
* `Person#addresses.{element}.city`
|
||||
*
|
||||
* @apiNote Whereas {@link #getPartName()} is local to this part, NavigableRole can be a compound path
|
||||
*
|
||||
* @see #getPartName()
|
||||
*/
|
||||
NavigableRole getNavigableRole();
|
||||
|
||||
/**
|
||||
* Create a DomainResult for a specific reference to this ModelPart.
|
||||
*/
|
||||
|
@ -69,4 +99,5 @@ public interface ModelPart extends MappingModelExpressable {
|
|||
|
||||
}
|
||||
|
||||
EntityMappingType findContainingEntityMapping();
|
||||
}
|
||||
|
|
|
@ -48,6 +48,10 @@ public abstract class AbstractEntityDiscriminatorMapping implements EntityDiscri
|
|||
this.mappingType = mappingType;
|
||||
}
|
||||
|
||||
public EntityPersister getEntityDescriptor() {
|
||||
return entityDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicType getBasicType() {
|
||||
return mappingType;
|
||||
|
|
|
@ -14,9 +14,11 @@ import org.hibernate.engine.FetchStrategy;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
|
@ -40,7 +42,7 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BasicValuedCollectionPart implements CollectionPart, BasicValuedModelPart {
|
||||
|
||||
private final NavigableRole navigableRole;
|
||||
private final CollectionPersister collectionDescriptor;
|
||||
private final Nature nature;
|
||||
private final BasicType mapper;
|
||||
|
@ -56,6 +58,7 @@ public class BasicValuedCollectionPart implements CollectionPart, BasicValuedMod
|
|||
BasicValueConverter valueConverter,
|
||||
String tableExpression,
|
||||
String columnExpression) {
|
||||
this.navigableRole = collectionDescriptor.getNavigableRole().append( nature.getName() );
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
this.nature = nature;
|
||||
this.mapper = mapper;
|
||||
|
@ -94,6 +97,11 @@ public class BasicValuedCollectionPart implements CollectionPart, BasicValuedMod
|
|||
return mapper.getMappedJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DomainResult<T> createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
|
@ -136,6 +144,11 @@ public class BasicValuedCollectionPart implements CollectionPart, BasicValuedMod
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return collectionDescriptor.getAttributeMapping().findContainingEntityMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcMapping getJdbcMapping() {
|
||||
return mapper;
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.hibernate.metamodel.mapping.ManagedMappingType;
|
|||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
|
@ -41,6 +42,7 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BasicValuedSingularAttributeMapping extends AbstractSingularAttributeMapping implements SingularAttributeMapping, BasicValuedModelPart {
|
||||
private final NavigableRole navigableRole;
|
||||
private final String tableExpression;
|
||||
private final String mappedColumnExpression;
|
||||
|
||||
|
@ -61,6 +63,7 @@ public class BasicValuedSingularAttributeMapping extends AbstractSingularAttribu
|
|||
ManagedMappingType declaringType,
|
||||
PropertyAccess propertyAccess) {
|
||||
super( attributeName, stateArrayPosition, attributeMetadataAccess, mappedFetchStrategy, basicType, declaringType, propertyAccess );
|
||||
this.navigableRole = declaringType.getNavigableRole().append( attributeName );
|
||||
this.tableExpression = tableExpression;
|
||||
this.mappedColumnExpression = mappedColumnExpression;
|
||||
this.valueConverter = valueConverter;
|
||||
|
@ -97,6 +100,11 @@ public class BasicValuedSingularAttributeMapping extends AbstractSingularAttribu
|
|||
return valueConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DomainResult<T> createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
|
|
|
@ -11,9 +11,11 @@ import org.hibernate.engine.FetchStrategy;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
|
@ -36,6 +38,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CollectionIdentifierDescriptorImpl implements CollectionIdentifierDescriptor {
|
||||
private final NavigableRole navigableRole;
|
||||
private final CollectionPersister collectionDescriptor;
|
||||
private final String containingTableName;
|
||||
private final String columnName;
|
||||
|
@ -46,6 +49,7 @@ public class CollectionIdentifierDescriptorImpl implements CollectionIdentifierD
|
|||
String containingTableName,
|
||||
String columnName,
|
||||
BasicType type) {
|
||||
this.navigableRole = collectionDescriptor.getNavigableRole().append( Nature.ID.getName() );
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
this.containingTableName = containingTableName;
|
||||
this.columnName = columnName;
|
||||
|
@ -92,6 +96,16 @@ public class CollectionIdentifierDescriptorImpl implements CollectionIdentifierD
|
|||
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return collectionDescriptor.getAttributeMapping().findContainingEntityMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFetchableName() {
|
||||
return null;
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.hibernate.metamodel.mapping.ManagedMappingType;
|
|||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
|
@ -32,6 +33,7 @@ import org.hibernate.sql.ast.SqlAstJoinType;
|
|||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.spi.SqlAstProcessingState;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
|
@ -56,12 +58,15 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
public class EmbeddedAttributeMapping
|
||||
extends AbstractSingularAttributeMapping
|
||||
implements EmbeddableValuedFetchable, Fetchable {
|
||||
private final NavigableRole navigableRole;
|
||||
|
||||
private final String tableExpression;
|
||||
private final String[] attrColumnNames;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public EmbeddedAttributeMapping(
|
||||
String name,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
String tableExpression,
|
||||
String[] attrColumnNames,
|
||||
|
@ -79,6 +84,7 @@ public class EmbeddedAttributeMapping
|
|||
declaringType,
|
||||
propertyAccess
|
||||
);
|
||||
this.navigableRole = navigableRole;
|
||||
this.tableExpression = tableExpression;
|
||||
this.attrColumnNames = attrColumnNames;
|
||||
}
|
||||
|
@ -92,7 +98,6 @@ public class EmbeddedAttributeMapping
|
|||
public EmbeddableMappingType getEmbeddableTypeDescriptor() {
|
||||
return getMappedTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeMapping getParentInjectionAttributeMapping() {
|
||||
// todo (6.0) : implement
|
||||
|
@ -153,6 +158,18 @@ public class EmbeddedAttributeMapping
|
|||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isCircular(FetchParent fetchParent, SqlAstProcessingState creationState) {
|
||||
// an embeddable can never be circular
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Fetch generateFetch(
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.metamodel.mapping.MappingType;
|
|||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
|
@ -49,6 +50,7 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedFetchable {
|
||||
private final NavigableRole navigableRole;
|
||||
private final CollectionPersister collectionDescriptor;
|
||||
private final Nature nature;
|
||||
private final EmbeddableMappingType embeddableMappingType;
|
||||
|
@ -68,6 +70,7 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
String containingTableExpression,
|
||||
List<String> columnExpressions,
|
||||
String sqlAliasStem) {
|
||||
this.navigableRole = collectionDescriptor.getNavigableRole().appendContainer( nature.getName() );
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
this.nature = nature;
|
||||
this.embeddableMappingType = embeddableMappingType;
|
||||
|
@ -232,6 +235,16 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
return getEmbeddableTypeDescriptor().getJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return collectionDescriptor.getAttributeMapping().findContainingEntityMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfFetchables() {
|
||||
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
|
||||
|
|
|
@ -20,12 +20,14 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
|||
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
|
@ -58,6 +60,7 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
* @author Andrea Boriero
|
||||
*/
|
||||
public class EmbeddedIdentifierMappingImpl implements CompositeIdentifierMapping, SingleAttributeIdentifierMapping, EmbeddableValuedFetchable {
|
||||
private final NavigableRole navigableRole;
|
||||
private final EntityMappingType entityMapping;
|
||||
private final String name;
|
||||
private final MappingType type;
|
||||
|
@ -77,6 +80,7 @@ public class EmbeddedIdentifierMappingImpl implements CompositeIdentifierMapping
|
|||
String tableExpression,
|
||||
String[] attrColumnNames,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
this.navigableRole = entityMapping.getNavigableRole().appendContainer( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
||||
this.entityMapping = entityMapping;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
|
@ -102,6 +106,11 @@ public class EmbeddedIdentifierMappingImpl implements CompositeIdentifierMapping
|
|||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||
return propertyAccess.getGetter().get( entity );
|
||||
|
@ -292,6 +301,11 @@ public class EmbeddedIdentifierMappingImpl implements CompositeIdentifierMapping
|
|||
getEmbeddableTypeDescriptor().visitColumns( consumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return entityMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAttributeCount() {
|
||||
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.hibernate.metamodel.mapping.EntityAssociationMapping;
|
|||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
@ -34,6 +34,8 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityCollectionPart implements CollectionPart, EntityAssociationMapping, EntityValuedFetchable {
|
||||
private final NavigableRole navigableRole;
|
||||
private final CollectionPersister collectionDescriptor;
|
||||
private final Nature nature;
|
||||
private final EntityMappingType entityMappingType;
|
||||
|
||||
|
@ -41,14 +43,19 @@ public class EntityCollectionPart implements CollectionPart, EntityAssociationMa
|
|||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public EntityCollectionPart(
|
||||
CollectionPersister collectionDescriptor,
|
||||
Nature nature,
|
||||
Value bootModelValue,
|
||||
EntityMappingType entityMappingType,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
this.navigableRole = collectionDescriptor.getNavigableRole().appendContainer( nature.getName() );
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
|
||||
this.nature = nature;
|
||||
this.entityMappingType = entityMappingType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public void finishInitialization(
|
||||
CollectionPersister collectionDescriptor,
|
||||
Collection bootValueMapping,
|
||||
|
@ -93,6 +100,11 @@ public class EntityCollectionPart implements CollectionPart, EntityAssociationMa
|
|||
return getEntityMappingType().getJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFetchableName() {
|
||||
return nature.getName();
|
||||
|
@ -152,6 +164,11 @@ public class EntityCollectionPart implements CollectionPart, EntityAssociationMa
|
|||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return collectionDescriptor.getAttributeMapping().findContainingEntityMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfFetchables() {
|
||||
return entityMappingType.getNumberOfFetchables();
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
|
@ -19,6 +22,7 @@ import org.hibernate.type.BasicType;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityDiscriminatorMappingImpl extends AbstractEntityDiscriminatorMapping {
|
||||
private final NavigableRole navigableRole;
|
||||
|
||||
public EntityDiscriminatorMappingImpl(
|
||||
EntityPersister entityDescriptor,
|
||||
|
@ -26,6 +30,7 @@ public class EntityDiscriminatorMappingImpl extends AbstractEntityDiscriminatorM
|
|||
String mappedColumnExpression,
|
||||
BasicType mappingType) {
|
||||
super( entityDescriptor, tableExpression, mappedColumnExpression, mappingType );
|
||||
this.navigableRole = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,4 +57,14 @@ public class EntityDiscriminatorMappingImpl extends AbstractEntityDiscriminatorM
|
|||
creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return getEntityDescriptor();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@ package org.hibernate.metamodel.mapping.internal;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
|
@ -21,19 +24,20 @@ import org.hibernate.type.BasicType;
|
|||
* @author Andrea Boriero
|
||||
*/
|
||||
public class JoinedSubclassDiscriminatorMappingImpl extends AbstractEntityDiscriminatorMapping {
|
||||
|
||||
private final NavigableRole navigableRole;
|
||||
private final CaseSearchedExpression caseSearchedExpression;
|
||||
private final List<ColumnReference> columnReferences;
|
||||
|
||||
public JoinedSubclassDiscriminatorMappingImpl(
|
||||
EntityPersister entityDescriptor,
|
||||
String tableExpression,
|
||||
String mappedColumExpression,
|
||||
String mappedColumnExpression,
|
||||
CaseSearchedExpression caseSearchedExpression,
|
||||
List<ColumnReference> columnReferences,
|
||||
BasicType mappingType) {
|
||||
super( entityDescriptor, tableExpression, mappedColumExpression, mappingType );
|
||||
super( entityDescriptor, tableExpression, mappedColumnExpression, mappingType );
|
||||
|
||||
this.navigableRole = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME );
|
||||
this.caseSearchedExpression = caseSearchedExpression;
|
||||
this.columnReferences = columnReferences;
|
||||
}
|
||||
|
@ -65,4 +69,13 @@ public class JoinedSubclassDiscriminatorMappingImpl extends AbstractEntityDiscri
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return getEntityDescriptor();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ import org.hibernate.metamodel.mapping.ColumnConsumer;
|
|||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
|
@ -66,6 +67,7 @@ import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
|||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.collection.SQLLoadableCollection;
|
||||
|
@ -130,6 +132,8 @@ public class MappingModelCreationHelper {
|
|||
final PropertyAccess propertyAccess = entityPersister.getRepresentationStrategy()
|
||||
.resolvePropertyAccess( bootEntityDescriptor.getIdentifierProperty() );
|
||||
|
||||
final NavigableRole idRole = entityPersister.getNavigableRole().append( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
||||
|
||||
return new BasicEntityIdentifierMapping() {
|
||||
@Override
|
||||
public PropertyAccess getPropertyAccess() {
|
||||
|
@ -178,6 +182,11 @@ public class MappingModelCreationHelper {
|
|||
consumer.accept( getMappedColumnExpression(), getContainingTableExpression(), getJdbcMapping() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return entityPersister;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJdbcTypes(
|
||||
Consumer<JdbcMapping> action,
|
||||
|
@ -200,6 +209,11 @@ public class MappingModelCreationHelper {
|
|||
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return idRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DomainResult<T> createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
|
@ -509,6 +523,7 @@ public class MappingModelCreationHelper {
|
|||
attrType,
|
||||
attributeMappingType -> new EmbeddedAttributeMapping(
|
||||
attrName,
|
||||
declaringType.getNavigableRole().append( attrName ),
|
||||
stateArrayPosition,
|
||||
tableExpression,
|
||||
attrColumnNames,
|
||||
|
@ -958,7 +973,7 @@ public class MappingModelCreationHelper {
|
|||
SingularAssociationAttributeMapping attributeMapping,
|
||||
Property bootProperty,
|
||||
ToOne bootValueMapping,
|
||||
EntityPersister declaringEntityDescriptor,
|
||||
EntityMappingType declaringEntityDescriptor,
|
||||
Dialect dialect,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
if ( attributeMapping.getForeignKeyDescriptor() != null ) {
|
||||
|
@ -1107,6 +1122,7 @@ public class MappingModelCreationHelper {
|
|||
final EntityPersister associatedEntity = creationProcess.getEntityPersister( indexEntityType.getAssociatedEntityName() );
|
||||
|
||||
final EntityCollectionPart indexDescriptor = new EntityCollectionPart(
|
||||
collectionDescriptor,
|
||||
CollectionPart.Nature.INDEX,
|
||||
bootMapKeyDescriptor,
|
||||
associatedEntity,
|
||||
|
@ -1197,6 +1213,7 @@ public class MappingModelCreationHelper {
|
|||
final EntityPersister associatedEntity = creationProcess.getEntityPersister( elementEntityType.getAssociatedEntityName() );
|
||||
|
||||
final EntityCollectionPart elementDescriptor = new EntityCollectionPart(
|
||||
collectionDescriptor,
|
||||
CollectionPart.Nature.ELEMENT,
|
||||
bootDescriptor.getElement(),
|
||||
associatedEntity,
|
||||
|
@ -1259,7 +1276,7 @@ public class MappingModelCreationHelper {
|
|||
String attrName,
|
||||
int stateArrayPosition,
|
||||
Property bootProperty,
|
||||
EntityPersister declaringType,
|
||||
ManagedMappingType declaringType,
|
||||
EntityType attrType,
|
||||
PropertyAccess propertyAccess,
|
||||
CascadeStyle cascadeStyle,
|
||||
|
@ -1310,7 +1327,7 @@ public class MappingModelCreationHelper {
|
|||
attributeMapping,
|
||||
bootProperty,
|
||||
(ToOne) bootProperty.getValue(),
|
||||
declaringType,
|
||||
declaringType.findContainingEntityMapping(),
|
||||
dialect,
|
||||
creationProcess
|
||||
);
|
||||
|
|
|
@ -6,29 +6,21 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
|
@ -42,6 +34,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NonAggregatedIdentifierMappingImpl implements CompositeIdentifierMapping {
|
||||
private final NavigableRole navigableRole;
|
||||
private final EntityMappingType entityMapping;
|
||||
|
||||
private final List<SingularAttributeMapping> idAttributeMappings;
|
||||
|
@ -54,6 +47,7 @@ public class NonAggregatedIdentifierMappingImpl implements CompositeIdentifierMa
|
|||
MappingModelCreationProcess creationProcess) {
|
||||
// todo (6.0) : handle MapsId and IdClass
|
||||
// todo (6.0) : implement SQL AST apis (DomainResult, e.g.)
|
||||
this.navigableRole = entityMapping.getNavigableRole().appendContainer( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
||||
this.entityMapping = entityMapping;
|
||||
this.idAttributeMappings = idAttributeMappings;
|
||||
}
|
||||
|
@ -68,6 +62,11 @@ public class NonAggregatedIdentifierMappingImpl implements CompositeIdentifierMa
|
|||
return entityMapping.getJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType getMappedTypeDescriptor() {
|
||||
return entityMapping;
|
||||
|
@ -108,4 +107,9 @@ public class NonAggregatedIdentifierMappingImpl implements CompositeIdentifierMa
|
|||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return entityMapping;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
|||
import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
|
||||
import org.hibernate.metamodel.mapping.ordering.OrderByFragmentTranslator;
|
||||
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
|
@ -331,6 +332,11 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
|||
return fetchStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return getCollectionDescriptor().getNavigableRole();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DomainResult<T> createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
|
|
|
@ -17,10 +17,12 @@ import org.hibernate.engine.FetchTiming;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
|
@ -259,6 +261,16 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
return jdbcMapping.getJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferringTableExpression() {
|
||||
return keyColumnContainingTable;
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.metamodel.mapping.ManagedMappingType;
|
|||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
|
@ -48,10 +49,13 @@ import org.hibernate.sql.results.graph.entity.internal.EntityFetchSelectImpl;
|
|||
*/
|
||||
public class SingularAssociationAttributeMapping extends AbstractSingularAttributeMapping
|
||||
implements EntityValuedFetchable, EntityAssociationMapping, TableGroupJoinProducer {
|
||||
private final NavigableRole navigableRole;
|
||||
private final String subRole;
|
||||
|
||||
private final String sqlAliasStem;
|
||||
private final boolean isNullable;
|
||||
private final boolean referringPrimaryKey;
|
||||
final protected boolean unwrapProxy;
|
||||
private final boolean unwrapProxy;
|
||||
private final String referencedPropertyName;
|
||||
|
||||
private ForeignKeyDescriptor foreignKeyDescriptor;
|
||||
|
@ -80,6 +84,15 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
|||
referencedPropertyName = value.getReferencedPropertyName();
|
||||
referringPrimaryKey = value.isReferenceToPrimaryKey();
|
||||
unwrapProxy = value.isUnwrapProxy();
|
||||
|
||||
this.navigableRole = declaringType.getNavigableRole().appendContainer( name );
|
||||
final int containerMarkerPosition = navigableRole.getFullPath().lastIndexOf( '#' );
|
||||
if ( containerMarkerPosition < 0 ) {
|
||||
subRole = name;
|
||||
}
|
||||
else {
|
||||
subRole = navigableRole.getFullPath().substring( containerMarkerPosition + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
public void setForeignKeyDescriptor(ForeignKeyDescriptor foreignKeyDescriptor) {
|
||||
|
@ -104,6 +117,61 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
|||
return getMappedTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCircular(FetchParent fetchParent, SqlAstProcessingState creationState) {
|
||||
// E.g. say we have a query like:
|
||||
// select p
|
||||
// from Person p
|
||||
// join fetch p.address a
|
||||
// join fetch a.owner
|
||||
//
|
||||
// where `owner` is the "owner" (in the mapped-by sense) of the association. In other words it is a
|
||||
// bi-directional mapping.
|
||||
//
|
||||
// This call is trying to generate a fetch for the NavigablePath `Person(p).address`.
|
||||
// What we need to determine is whether owner is the same as address's container. This might include
|
||||
// multiple parent-paths which we need to walk up to find the container (an entity of collection)
|
||||
|
||||
final NavigablePath parentNavigablePath = fetchParent.getNavigablePath();
|
||||
NavigablePath pathToParentParent = parentNavigablePath.getParent();
|
||||
if ( pathToParentParent == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < numberOfPathElementsToContainer; i++ ) {
|
||||
pathToParentParent = pathToParentParent.getParent();
|
||||
}
|
||||
|
||||
assert pathToParentParent != null;
|
||||
|
||||
final ModelPartContainer modelPart = creationState.getSqlAstCreationState()
|
||||
.getFromClauseAccess()
|
||||
.findTableGroup( pathToParentParent )
|
||||
.getModelPart();
|
||||
|
||||
|
||||
final ModelPart subPart = modelPart.findSubPart( parentNavigablePath.getLocalName(), null );
|
||||
if ( subPart instanceof EntityAssociationMapping ) {
|
||||
final EntityAssociationMapping part = (EntityAssociationMapping) subPart;
|
||||
|
||||
if ( parentNavigablePath.getLocalName().equals( referencedPropertyName )
|
||||
&& part.getFetchableName().equals( referencedPropertyName ) ) {
|
||||
return true;
|
||||
}
|
||||
else if ( part.getKeyTargetMatchPart() != null
|
||||
&& part.getKeyTargetMatchPart().getPartName().equals( getAttributeName() ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch generateFetch(
|
||||
FetchParent fetchParent,
|
||||
|
@ -254,43 +322,6 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
|||
return sqlAliasStem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCircular(FetchParent fetchParent, SqlAstProcessingState creationState) {
|
||||
final NavigablePath panentNaviblePath = fetchParent.getNavigablePath();
|
||||
final NavigablePath parentParentNavigablePath = panentNaviblePath.getParent();
|
||||
if ( parentParentNavigablePath == null ) {
|
||||
return false;
|
||||
}
|
||||
if ( getAttributeName().equals( parentParentNavigablePath.getLocalName() ) ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
final ModelPartContainer modelPart = creationState.getSqlAstCreationState()
|
||||
.getFromClauseAccess()
|
||||
.findTableGroup( parentParentNavigablePath )
|
||||
.getModelPart();
|
||||
|
||||
final ModelPart subPart = modelPart.findSubPart( panentNaviblePath.getLocalName(), null );
|
||||
if ( subPart instanceof EntityAssociationMapping ) {
|
||||
final EntityAssociationMapping part = (EntityAssociationMapping) subPart;
|
||||
|
||||
if ( panentNaviblePath.getLocalName().equals( referencedPropertyName )
|
||||
&& part.getFetchableName().equals( referencedPropertyName ) ) {
|
||||
return true;
|
||||
}
|
||||
else if ( part.getKeyTargetMatchPart() != null
|
||||
&& part.getKeyTargetMatchPart().getPartName().equals( getAttributeName() ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return isNullable;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,10 @@ public class NavigableRole implements DotIdentifierSequence {
|
|||
private final String fullPath;
|
||||
|
||||
public NavigableRole(NavigableRole parent, String localName) {
|
||||
this( parent, localName, '.' );
|
||||
}
|
||||
|
||||
public NavigableRole(NavigableRole parent, String localName, char separator) {
|
||||
this.parent = parent;
|
||||
this.localName = localName;
|
||||
|
||||
|
@ -45,7 +49,7 @@ public class NavigableRole implements DotIdentifierSequence {
|
|||
prefix = "";
|
||||
}
|
||||
else {
|
||||
prefix = resolvedParent + '.';
|
||||
prefix = resolvedParent + separator;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -64,8 +68,18 @@ public class NavigableRole implements DotIdentifierSequence {
|
|||
this( "" );
|
||||
}
|
||||
|
||||
public NavigableRole append(String property) {
|
||||
return new NavigableRole( this, property );
|
||||
public NavigableRole append(String name) {
|
||||
return new NavigableRole( this, name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses `#` as the separator rather than `.`. The intention being that the incoming name is a
|
||||
* {@link org.hibernate.metamodel.mapping.ModelPartContainer} of some sort
|
||||
*
|
||||
* todo (6.0) : better name?
|
||||
*/
|
||||
public NavigableRole appendContainer(String name) {
|
||||
return new NavigableRole( this, name, '#' );
|
||||
}
|
||||
|
||||
public NavigableRole getParent() {
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.hibernate.metadata.ClassMetadata;
|
|||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.internal.InFlightEntityMappingType;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
|
@ -116,8 +115,6 @@ public interface EntityPersister extends EntityDefinition, EntityValuedModelPart
|
|||
*/
|
||||
SessionFactoryImplementor getFactory();
|
||||
|
||||
NavigableRole getNavigableRole();
|
||||
|
||||
@Override
|
||||
default String getSqlAliasStem() {
|
||||
return SqlAliasStemHelper.INSTANCE.generateStemFromEntityName( getEntityName() );
|
||||
|
|
|
@ -12,7 +12,9 @@ import org.hibernate.LockMode;
|
|||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.BiDirectionalFetch;
|
||||
|
@ -112,6 +114,16 @@ public class BiDirectionalFetchImpl implements BiDirectionalFetch, Fetchable {
|
|||
return fetchable.getFetchableName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return fetchable.getNavigableRole();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType findContainingEntityMapping() {
|
||||
return fetchable.findContainingEntityMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingType getPartMappingType() {
|
||||
return fetchable.getPartMappingType();
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.annotations.embedded;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.hamcrest.CoreMatchers;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
EmbeddedCircularFetchTests.LeafEntity.class,
|
||||
EmbeddedCircularFetchTests.RootEntity.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
@ServiceRegistry(settings = {
|
||||
@ServiceRegistry.Setting(name = AvailableSettings.IMPLICIT_NAMING_STRATEGY, value = "jpa"),
|
||||
@ServiceRegistry.Setting(name = AvailableSettings.GENERATE_STATISTICS, value = "true")
|
||||
})
|
||||
public class EmbeddedCircularFetchTests {
|
||||
// @Test
|
||||
// @TestForIssue(jiraKey = "HHH-9642")
|
||||
// public void testEmbeddedAndOneToManyHql(SessionFactoryScope scope) {
|
||||
// scope.inTransaction(
|
||||
// session -> {
|
||||
// InternetProvider provider = new InternetProvider();
|
||||
// provider.setBrandName( "Fido" );
|
||||
// LegalStructure structure = new LegalStructure();
|
||||
// structure.setCountry( "Canada" );
|
||||
// structure.setName( "Rogers" );
|
||||
// provider.setOwner( structure );
|
||||
// session.persist( provider );
|
||||
// Manager manager = new Manager();
|
||||
// manager.setName( "Bill" );
|
||||
// manager.setEmployer( provider );
|
||||
// structure.getTopManagement().add( manager );
|
||||
// session.persist( manager );
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// scope.inTransaction(
|
||||
// session -> {
|
||||
// InternetProvider internetProviderQueried =
|
||||
// (InternetProvider) session.createQuery( "from InternetProvider" ).uniqueResult();
|
||||
// assertFalse( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
//
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// scope.inTransaction(
|
||||
// session -> {
|
||||
// InternetProvider internetProviderQueried =
|
||||
// (InternetProvider) session.createQuery(
|
||||
// "from InternetProvider i join fetch i.owner.topManagement" )
|
||||
// .uniqueResult();
|
||||
// assertTrue( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
//
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// InternetProvider provider = scope.fromTransaction(
|
||||
// session -> {
|
||||
// InternetProvider internetProviderQueried =
|
||||
// (InternetProvider) session.createQuery(
|
||||
// "from InternetProvider i join fetch i.owner o join fetch o.topManagement" )
|
||||
// .uniqueResult();
|
||||
// assertTrue( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
// return internetProviderQueried;
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// scope.inTransaction(
|
||||
// session -> {
|
||||
// InternetProvider internetProvider = session.get( InternetProvider.class, provider.getId() );
|
||||
// Manager manager = internetProvider.getOwner().getTopManagement().iterator().next();
|
||||
// session.delete( manager );
|
||||
// session.delete( internetProvider );
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-9642")
|
||||
public void testCircularFetchAcrossComponent(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
RootEntity root = new RootEntity();
|
||||
root.id = 1;
|
||||
session.save( root );
|
||||
|
||||
LeafEntity leafEntity1 = new LeafEntity();
|
||||
leafEntity1.id = 10;
|
||||
|
||||
LeafEntity leafEntity2 = new LeafEntity();
|
||||
leafEntity2.id = 11;
|
||||
|
||||
session.save( leafEntity1 );
|
||||
session.save( leafEntity2 );
|
||||
|
||||
leafEntity2.rootEntity = root;
|
||||
leafEntity1.rootEntity = root;
|
||||
root.intermediateComponent = new IntermediateComponent();
|
||||
|
||||
root.intermediateComponent.leaves = new HashSet<>( );
|
||||
root.intermediateComponent.leaves.add( leafEntity1 );
|
||||
root.intermediateComponent.leaves.add( leafEntity2 );
|
||||
}
|
||||
);
|
||||
|
||||
// scope.inTransaction(
|
||||
// session -> {
|
||||
// InternetProvider internetProviderQueried =
|
||||
// (InternetProvider) session.createQuery( "from InternetProvider" ).uniqueResult();
|
||||
// assertFalse( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
//
|
||||
// }
|
||||
// );
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.getSessionFactory().getStatistics().clear();
|
||||
final RootEntity result = session.createQuery(
|
||||
"from RootEntity r join fetch r.intermediateComponent.leaves",
|
||||
RootEntity.class
|
||||
).uniqueResult();
|
||||
assertTrue( Hibernate.isInitialized( result.getIntermediateComponent().getLeaves() ) );
|
||||
assertThat( result.getIntermediateComponent().getLeaves().size(), is( 1 ) );
|
||||
|
||||
assertThat( session.getSessionFactory().getStatistics().getPrepareStatementCount(), is( 1 ) );
|
||||
}
|
||||
);
|
||||
|
||||
// InternetProvider provider = scope.fromTransaction(
|
||||
// session -> {
|
||||
// InternetProvider internetProviderQueried =
|
||||
// (InternetProvider) session.createQuery(
|
||||
// "from InternetProvider i join fetch i.owner o join fetch o.topManagement" )
|
||||
// .uniqueResult();
|
||||
// LegalStructure owner = internetProviderQueried.getOwner();
|
||||
// assertTrue( Hibernate.isInitialized( owner ));
|
||||
// assertTrue( Hibernate.isInitialized( owner.getTopManagement() ) );
|
||||
// return internetProviderQueried;
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// scope.inTransaction(
|
||||
// session -> {
|
||||
// InternetProvider internetProvider = session.get( InternetProvider.class, provider.getId() );
|
||||
// Manager manager = internetProvider.getOwner().getTopManagement().iterator().next();
|
||||
// session.delete( manager );
|
||||
// session.delete( internetProvider );
|
||||
// }
|
||||
// );
|
||||
}
|
||||
|
||||
@Entity( name = "RootEntity" )
|
||||
@Table( name = "root" )
|
||||
public static class RootEntity {
|
||||
private Integer id;
|
||||
private IntermediateComponent intermediateComponent;
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Embedded
|
||||
public IntermediateComponent getIntermediateComponent() {
|
||||
return intermediateComponent;
|
||||
}
|
||||
|
||||
public void setIntermediateComponent(IntermediateComponent intermediateComponent) {
|
||||
this.intermediateComponent = intermediateComponent;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class IntermediateComponent {
|
||||
private String name;
|
||||
private Set<LeafEntity> leaves;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@OneToMany( mappedBy = "rootEntity" )
|
||||
public Set<LeafEntity> getLeaves() {
|
||||
return leaves;
|
||||
}
|
||||
|
||||
public void setLeaves(Set<LeafEntity> leaves) {
|
||||
this.leaves = leaves;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity( name = "LeafEntity" )
|
||||
@Table( name = "leaf" )
|
||||
public static class LeafEntity {
|
||||
private Integer id;
|
||||
private String name;
|
||||
private RootEntity rootEntity;
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn
|
||||
public RootEntity getRootEntity() {
|
||||
return rootEntity;
|
||||
}
|
||||
|
||||
public void setRootEntity(RootEntity rootEntity) {
|
||||
this.rootEntity = rootEntity;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.annotations.embedded;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
InternetProvider.class,
|
||||
CorpType.class,
|
||||
Nationality.class,
|
||||
Manager.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
@ServiceRegistry(settings = {
|
||||
@ServiceRegistry.Setting(name = AvailableSettings.IMPLICIT_NAMING_STRATEGY, value = "jpa")
|
||||
})
|
||||
public class EmbeddedTest2 {
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-9642")
|
||||
public void testEmbeddedAndOneToManyHql(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
InternetProvider provider = new InternetProvider();
|
||||
provider.setBrandName( "Fido" );
|
||||
LegalStructure structure = new LegalStructure();
|
||||
structure.setCountry( "Canada" );
|
||||
structure.setName( "Rogers" );
|
||||
provider.setOwner( structure );
|
||||
session.persist( provider );
|
||||
Manager manager = new Manager();
|
||||
manager.setName( "Bill" );
|
||||
manager.setEmployer( provider );
|
||||
structure.getTopManagement().add( manager );
|
||||
session.persist( manager );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
InternetProvider internetProviderQueried =
|
||||
(InternetProvider) session.createQuery( "from InternetProvider" ).uniqueResult();
|
||||
assertFalse( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
InternetProvider internetProviderQueried =
|
||||
(InternetProvider) session.createQuery(
|
||||
"from InternetProvider i join fetch i.owner.topManagement" )
|
||||
.uniqueResult();
|
||||
assertTrue( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
InternetProvider provider = scope.fromTransaction(
|
||||
session -> {
|
||||
InternetProvider internetProviderQueried =
|
||||
(InternetProvider) session.createQuery(
|
||||
"from InternetProvider i join fetch i.owner o join fetch o.topManagement" )
|
||||
.uniqueResult();
|
||||
assertTrue( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
return internetProviderQueried;
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
InternetProvider internetProvider = session.get( InternetProvider.class, provider.getId() );
|
||||
Manager manager = internetProvider.getOwner().getTopManagement().iterator().next();
|
||||
session.delete( manager );
|
||||
session.delete( internetProvider );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-9642")
|
||||
public void testEmbeddedAndOneToManyHqlFetch(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
InternetProvider provider = new InternetProvider();
|
||||
provider.setBrandName( "Fido" );
|
||||
LegalStructure structure = new LegalStructure();
|
||||
structure.setCountry( "Canada" );
|
||||
structure.setName( "Rogers" );
|
||||
provider.setOwner( structure );
|
||||
session.persist( provider );
|
||||
Manager manager = new Manager();
|
||||
manager.setName( "Bill" );
|
||||
manager.setEmployer( provider );
|
||||
structure.getTopManagement().add( manager );
|
||||
session.persist( manager );
|
||||
}
|
||||
);
|
||||
|
||||
// scope.inTransaction(
|
||||
// session -> {
|
||||
// InternetProvider internetProviderQueried =
|
||||
// (InternetProvider) session.createQuery( "from InternetProvider" ).uniqueResult();
|
||||
// assertFalse( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
//
|
||||
// }
|
||||
// );
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
InternetProvider internetProviderQueried =
|
||||
(InternetProvider) session.createQuery(
|
||||
"from InternetProvider i join fetch i.owner.topManagement" )
|
||||
.uniqueResult();
|
||||
assertTrue( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
InternetProvider provider = scope.fromTransaction(
|
||||
session -> {
|
||||
InternetProvider internetProviderQueried =
|
||||
(InternetProvider) session.createQuery(
|
||||
"from InternetProvider i join fetch i.owner o join fetch o.topManagement" )
|
||||
.uniqueResult();
|
||||
LegalStructure owner = internetProviderQueried.getOwner();
|
||||
assertTrue( Hibernate.isInitialized( owner ));
|
||||
assertTrue( Hibernate.isInitialized( owner.getTopManagement() ) );
|
||||
return internetProviderQueried;
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
InternetProvider internetProvider = session.get( InternetProvider.class, provider.getId() );
|
||||
Manager manager = internetProvider.getOwner().getTopManagement().iterator().next();
|
||||
session.delete( manager );
|
||||
session.delete( internetProvider );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue