initial work on circular fetch detection across embeddables

This commit is contained in:
Steve Ebersole 2020-01-17 09:30:35 -06:00 committed by Andrea Boriero
parent 8c806a5a16
commit 4f750cdc55
25 changed files with 608 additions and 227 deletions

View File

@ -26,4 +26,9 @@ public interface AttributeMapping extends ModelPart, ValueMapping {
ManagedMappingType getDeclaringType();
PropertyAccess getPropertyAccess();
@Override
default EntityMappingType findContainingEntityMapping() {
return getDeclaringType().findContainingEntityMapping();
}
}

View File

@ -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();

View File

@ -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;

View File

@ -54,6 +54,11 @@ public interface EntityMappingType extends ManagedMappingType, Loadable {
String getEntityName();
@Override
default EntityMappingType findContainingEntityMapping() {
return this;
}
@Override
default String getPartName() {
return getEntityName();

View File

@ -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();
}

View File

@ -48,6 +48,10 @@ public abstract class AbstractEntityDiscriminatorMapping implements EntityDiscri
this.mappingType = mappingType;
}
public EntityPersister getEntityDescriptor() {
return entityDescriptor;
}
@Override
public BasicType getBasicType() {
return mappingType;

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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(

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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
);

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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;

View File

@ -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;
}

View File

@ -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() {

View File

@ -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() );

View File

@ -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();

View File

@ -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;
}
}
}

View File

@ -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 );
}
);
}
}