Re-enabled additional Inheritance related tests and fixed issues with initializer for subclasses

This commit is contained in:
Andrea Boriero 2020-07-02 17:58:36 +01:00
parent 923a7d8d07
commit 7470138e0f
32 changed files with 347 additions and 166 deletions

View File

@ -312,6 +312,7 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
.getFromClauseAccess() .getFromClauseAccess()
.getTableGroup( fetchParent.getNavigablePath() ); .getTableGroup( fetchParent.getNavigablePath() );
return new CircularFetchImpl( return new CircularFetchImpl(
this,
getEntityMappingType(), getEntityMappingType(),
getTiming(), getTiming(),
fetchablePath, fetchablePath,

View File

@ -55,12 +55,12 @@ public abstract class AbstractFetchParent implements FetchParent {
} }
@Override @Override
public Fetch findFetch(String fetchableName) { public Fetch findFetch(Fetchable fetchable) {
if ( fetches != null ) { if ( fetches != null ) {
for ( Fetch fetch : fetches ) { for ( Fetch fetch : fetches ) {
final Fetchable fetchedMapping = fetch.getFetchedMapping(); final Fetchable fetchedMapping = fetch.getFetchedMapping();
if ( fetchedMapping != null && fetchedMapping if ( fetchedMapping != null
.getFetchableName().equals( fetchableName ) ) { && fetchedMapping.getNavigableRole().equals( fetchable.getNavigableRole() ) ) {
return fetch; return fetch;
} }
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.sql.results.graph;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
@ -15,6 +16,11 @@ import org.hibernate.sql.ast.spi.SqlAstCreationContext;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface AssemblerCreationState { public interface AssemblerCreationState {
Initializer resolveInitializer(NavigablePath navigablePath, Supplier<Initializer> producer);
Initializer resolveInitializer(
NavigablePath navigablePath,
ModelPart fetchedModelPart,
Supplier<Initializer> producer);
SqlAstCreationContext getSqlAstCreationContext(); SqlAstCreationContext getSqlAstCreationContext();
} }

View File

@ -63,5 +63,5 @@ public interface FetchParent extends DomainResultGraphNode {
*/ */
List<Fetch> getFetches(); List<Fetch> getFetches();
Fetch findFetch(String fetchableName); Fetch findFetch(Fetchable fetchable);
} }

View File

@ -21,6 +21,7 @@ import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.graph.collection.CollectionResultGraphNode; import org.hibernate.sql.results.graph.collection.CollectionResultGraphNode;
@ -81,6 +82,7 @@ public class CollectionDomainResult implements DomainResult, CollectionResultGra
public DomainResultAssembler createResultAssembler(AssemblerCreationState creationState) { public DomainResultAssembler createResultAssembler(AssemblerCreationState creationState) {
final CollectionInitializer initializer = (CollectionInitializer) creationState.resolveInitializer( final CollectionInitializer initializer = (CollectionInitializer) creationState.resolveInitializer(
getNavigablePath(), getNavigablePath(),
getReferencedModePart(),
() -> { () -> {
final DomainResultAssembler fkAssembler = fkResult.createResultAssembler( creationState ); final DomainResultAssembler fkAssembler = fkResult.createResultAssembler( creationState );
@ -120,7 +122,7 @@ public class CollectionDomainResult implements DomainResult, CollectionResultGra
} }
@Override @Override
public Fetch findFetch(String fetchableName) { public Fetch findFetch(Fetchable fetchable) {
return null; return null;
} }

View File

@ -28,6 +28,7 @@ public class DelayedCollectionAssembler extends AbstractCollectionAssembler {
fetchedMapping, fetchedMapping,
() -> (CollectionInitializer) creationState.resolveInitializer( () -> (CollectionInitializer) creationState.resolveInitializer(
fetchPath, fetchPath,
fetchedMapping,
() -> new DelayedCollectionInitializer( fetchPath, fetchedMapping, parentAccess ) () -> new DelayedCollectionInitializer( fetchPath, fetchedMapping, parentAccess )
) )

View File

@ -25,6 +25,7 @@ import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -108,6 +109,7 @@ public class EagerCollectionFetch extends CollectionFetch implements FetchParent
public DomainResultAssembler createAssembler(FetchParentAccess parentAccess, AssemblerCreationState creationState) { public DomainResultAssembler createAssembler(FetchParentAccess parentAccess, AssemblerCreationState creationState) {
final CollectionInitializer initializer = (CollectionInitializer) creationState.resolveInitializer( final CollectionInitializer initializer = (CollectionInitializer) creationState.resolveInitializer(
getNavigablePath(), getNavigablePath(),
getReferencedModePart(),
() -> { () -> {
final DomainResultAssembler keyContainerAssembler = keyContainerResult.createResultAssembler( creationState ); final DomainResultAssembler keyContainerAssembler = keyContainerResult.createResultAssembler( creationState );
@ -160,17 +162,17 @@ public class EagerCollectionFetch extends CollectionFetch implements FetchParent
} }
@Override @Override
public Fetch findFetch(String fetchableName) { public Fetch findFetch(Fetchable fetchable) {
if ( CollectionPart.Nature.ELEMENT.getName().equals( fetchableName ) ) { if ( CollectionPart.Nature.ELEMENT.getName().equals( fetchable.getFetchableName() ) ) {
return elementFetch; return elementFetch;
} }
else if ( CollectionPart.Nature.INDEX.getName().equals( fetchableName ) ) { else if ( CollectionPart.Nature.INDEX.getName().equals( fetchable.getFetchableName() ) ) {
return indexFetch; return indexFetch;
} }
else { else {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Unknown fetchable [" + getFetchedMapping().getCollectionDescriptor().getRole() + "Unknown fetchable [" + getFetchedMapping().getCollectionDescriptor().getRole() +
" -> " + fetchableName + "]" " -> " + fetchable.getFetchableName() + "]"
); );
} }
} }

View File

@ -26,6 +26,7 @@ public class SelectEagerCollectionAssembler extends AbstractCollectionAssembler
fetchedMapping, fetchedMapping,
() -> (CollectionInitializer) creationState.resolveInitializer( () -> (CollectionInitializer) creationState.resolveInitializer(
fetchPath, fetchPath,
fetchedMapping,
() -> new SelectEagerCollectionInitializer( fetchPath, fetchedMapping, parentAccess ) () -> new SelectEagerCollectionInitializer( fetchPath, fetchedMapping, parentAccess )
) )
); );

View File

@ -55,7 +55,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
embeddableTypeDescriptor.visitStateArrayContributors( embeddableTypeDescriptor.visitStateArrayContributors(
stateArrayContributor -> { stateArrayContributor -> {
final Fetch fetch = resultDescriptor.findFetch( stateArrayContributor.getFetchableName() ); final Fetch fetch = resultDescriptor.findFetch( stateArrayContributor );
final DomainResultAssembler stateAssembler = fetch == null final DomainResultAssembler stateAssembler = fetch == null
? new NullValueAssembler( stateArrayContributor.getJavaTypeDescriptor() ) ? new NullValueAssembler( stateArrayContributor.getJavaTypeDescriptor() )

View File

@ -113,6 +113,7 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
final EmbeddableInitializer initializer = (EmbeddableInitializer) creationState.resolveInitializer( final EmbeddableInitializer initializer = (EmbeddableInitializer) creationState.resolveInitializer(
getNavigablePath(), getNavigablePath(),
getReferencedModePart(),
() -> new EmbeddableFetchInitializer( () -> new EmbeddableFetchInitializer(
parentAccess, parentAccess,
this, this,

View File

@ -39,6 +39,7 @@ public class EmbeddableForeignKeyResultImpl<T>
extends AbstractFetchParent extends AbstractFetchParent
implements EmbeddableResultGraphNode, DomainResult<T> { implements EmbeddableResultGraphNode, DomainResult<T> {
private static final String ROLE_LOCAL_NAME = "{fk}";
private final String resultVariable; private final String resultVariable;
public EmbeddableForeignKeyResultImpl( public EmbeddableForeignKeyResultImpl(
@ -47,15 +48,15 @@ public class EmbeddableForeignKeyResultImpl<T>
EmbeddableValuedModelPart embeddableValuedModelPart, EmbeddableValuedModelPart embeddableValuedModelPart,
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
super( embeddableValuedModelPart.getEmbeddableTypeDescriptor(), navigablePath ); super( embeddableValuedModelPart.getEmbeddableTypeDescriptor(), navigablePath.append( ROLE_LOCAL_NAME ) );
this.resultVariable = resultVariable; this.resultVariable = resultVariable;
fetches = new ArrayList<>(); fetches = new ArrayList<>();
MutableInteger index = new MutableInteger(); MutableInteger index = new MutableInteger();
embeddableValuedModelPart.visitFetchables( embeddableValuedModelPart.visitFetchables(
fetchable -> { fetchable ->
generateFetches( sqlSelections, navigablePath, creationState, index, fetchable ); generateFetches( sqlSelections, navigablePath, creationState, index, fetchable )
}, ,
null null
); );
} }
@ -120,6 +121,7 @@ public class EmbeddableForeignKeyResultImpl<T>
public DomainResultAssembler<T> createResultAssembler(AssemblerCreationState creationState) { public DomainResultAssembler<T> createResultAssembler(AssemblerCreationState creationState) {
final EmbeddableInitializer initializer = (EmbeddableInitializer) creationState.resolveInitializer( final EmbeddableInitializer initializer = (EmbeddableInitializer) creationState.resolveInitializer(
getNavigablePath(), getNavigablePath(),
getReferencedModePart(),
() -> new EmbeddableResultInitializer(this, creationState ) () -> new EmbeddableResultInitializer(this, creationState )
); );
@ -127,19 +129,14 @@ public class EmbeddableForeignKeyResultImpl<T>
return new EmbeddableAssembler( initializer ); return new EmbeddableAssembler( initializer );
} }
@Override
public NavigablePath getNavigablePath() {
return super.getNavigablePath().append( "{fk}");
}
@Override @Override
public EmbeddableMappingType getReferencedMappingType() { public EmbeddableMappingType getReferencedMappingType() {
return (EmbeddableMappingType) getFetchContainer().getPartMappingType(); return (EmbeddableMappingType) getFetchContainer().getPartMappingType();
} }
@Override @Override
public Fetch findFetch(String fetchableName) { public Fetch findFetch(Fetchable fetchable) {
return super.findFetch( fetchableName ); return super.findFetch( fetchable );
} }
@Override @Override

View File

@ -87,6 +87,7 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
public DomainResultAssembler<T> createResultAssembler(AssemblerCreationState creationState) { public DomainResultAssembler<T> createResultAssembler(AssemblerCreationState creationState) {
final EmbeddableInitializer initializer = (EmbeddableInitializer) creationState.resolveInitializer( final EmbeddableInitializer initializer = (EmbeddableInitializer) creationState.resolveInitializer(
getNavigablePath(), getNavigablePath(),
getReferencedModePart(),
() -> new EmbeddableResultInitializer( () -> new EmbeddableResultInitializer(
this, this,
creationState creationState

View File

@ -34,6 +34,8 @@ import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener; import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Loadable;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
@ -67,6 +69,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
private final EntityPersister entityDescriptor; private final EntityPersister entityDescriptor;
private final EntityPersister rootEntityDescriptor; private final EntityPersister rootEntityDescriptor;
private EntityPersister concreteDescriptor;
private final NavigablePath navigablePath; private final NavigablePath navigablePath;
private final LockMode lockMode; private final LockMode lockMode;
@ -80,7 +83,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
private final Map<AttributeMapping, DomainResultAssembler> assemblerMap; private final Map<AttributeMapping, DomainResultAssembler> assemblerMap;
// per-row state // per-row state
private EntityPersister concreteDescriptor; private final EntityValuedModelPart referencedModelPart;
private EntityKey entityKey; private EntityKey entityKey;
private Object entityInstance; private Object entityInstance;
private boolean missing; private boolean missing;
@ -100,7 +103,8 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
super( ); super( );
this.entityDescriptor = (EntityPersister) resultDescriptor.getEntityValuedModelPart().getEntityMappingType(); this.referencedModelPart = resultDescriptor.getEntityValuedModelPart();
this.entityDescriptor = (EntityPersister) referencedModelPart.getEntityMappingType();
final String rootEntityName = entityDescriptor.getRootEntityName(); final String rootEntityName = entityDescriptor.getRootEntityName();
if ( rootEntityName == null || rootEntityName.equals( entityDescriptor.getEntityName() ) ) { if ( rootEntityName == null || rootEntityName.equals( entityDescriptor.getEntityName() ) ) {
@ -117,10 +121,15 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
this.identifierAssembler = identifierResult.createResultAssembler( this.identifierAssembler = identifierResult.createResultAssembler(
new AssemblerCreationState() { new AssemblerCreationState() {
@Override @Override
public Initializer resolveInitializer(NavigablePath navigablePath, Supplier<Initializer> producer) { public Initializer resolveInitializer(
NavigablePath navigablePath,
ModelPart fetchedModelPart,
Supplier<Initializer> producer) {
for ( int i = 0; i < identifierInitializers.size(); i++ ) { for ( int i = 0; i < identifierInitializers.size(); i++ ) {
final Initializer existing = identifierInitializers.get( i ); final Initializer existing = identifierInitializers.get( i );
if ( existing.getNavigablePath().equals( navigablePath ) ) { if ( existing.getNavigablePath().equals( navigablePath )
&& fetchedModelPart.getNavigableRole().equals(
existing.getInitializedPart().getNavigableRole() ) ) {
return existing; return existing;
} }
} }
@ -185,7 +194,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
// note that lazy proxies or uninitialized collections count against // note that lazy proxies or uninitialized collections count against
// that in the affirmative // that in the affirmative
final Fetch fetch = resultDescriptor.findFetch( fetchable.getFetchableName() ); final Fetch fetch = resultDescriptor.findFetch( fetchable );
final DomainResultAssembler stateAssembler; final DomainResultAssembler stateAssembler;
if ( fetch == null ) { if ( fetch == null ) {
@ -201,6 +210,11 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
); );
} }
@Override
public ModelPart getInitializedPart(){
return referencedModelPart;
}
protected abstract String getSimpleConcreteImplName(); protected abstract String getSimpleConcreteImplName();
public NavigablePath getNavigablePath() { public NavigablePath getNavigablePath() {
@ -268,6 +282,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession(); final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession();
concreteDescriptor = determineConcreteEntityDescriptor( rowProcessingState, session ); concreteDescriptor = determineConcreteEntityDescriptor( rowProcessingState, session );
if ( concreteDescriptor == null ) {
missing = true;
return;
}
initializeIdentifier( rowProcessingState ); initializeIdentifier( rowProcessingState );
resolveEntityKey( rowProcessingState ); resolveEntityKey( rowProcessingState );
@ -306,21 +324,22 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions() rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions()
); );
final String concreteEntityName = ( (Loadable) rootEntityDescriptor ).getSubclassForDiscriminatorValue( discriminatorValue ); final String concreteEntityName = ( (Loadable) entityDescriptor ).getSubclassForDiscriminatorValue( discriminatorValue );
if ( concreteEntityName == null ) { if ( concreteEntityName == null ) {
// oops - we got an instance of another class hierarchy branch // oops - we got an instance of another class hierarchy branch
throw new WrongClassException( // throw new WrongClassException(
"Discriminator: " + discriminatorValue, // "Discriminator: " + discriminatorValue,
entityKey.getIdentifier(), // entityKey.getIdentifier(),
entityDescriptor.getEntityName() // entityDescriptor.getEntityName()
); // );
return null;
} }
final EntityPersister concreteType = session.getFactory().getMetamodel().findEntityDescriptor( concreteEntityName ); final EntityPersister concreteType = session.getFactory().getMetamodel().findEntityDescriptor( concreteEntityName );
// verify that the `entityDescriptor` is either == concreteType or its super-type // verify that the `entityDescriptor` is either == concreteType or its super-type
assert concreteType.isTypeOrSuperType( rootEntityDescriptor ); assert concreteType.isTypeOrSuperType( entityDescriptor );
return concreteType; return concreteType;
} }

View File

@ -19,10 +19,6 @@ import org.hibernate.persister.entity.EntityPersister;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface EntityInitializer extends Initializer, FetchParentAccess { public interface EntityInitializer extends Initializer, FetchParentAccess {
@Override
default ModelPart getInitializedPart() {
return getEntityDescriptor();
}
/** /**
* Get the descriptor for the type of entity being initialized * Get the descriptor for the type of entity being initialized

View File

@ -13,6 +13,7 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.graph.entity.EntityFetch;
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable; import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
@ -59,7 +60,7 @@ public abstract class AbstractNonJoinedEntityFetch implements EntityFetch {
} }
@Override @Override
public Fetch findFetch(String fetchableName) { public Fetch findFetch(Fetchable fetchable) {
return null; return null;
} }

View File

@ -47,11 +47,13 @@ public class EntityDelayedFetchImpl extends AbstractNonJoinedEntityFetch {
public DomainResultAssembler createAssembler( public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
final NavigablePath navigablePath = getNavigablePath();
final EntityInitializer entityInitializer = (EntityInitializer) creationState.resolveInitializer( final EntityInitializer entityInitializer = (EntityInitializer) creationState.resolveInitializer(
getNavigablePath(), navigablePath,
getEntityValuedModelPart(),
() -> new EntityDelayedFetchInitializer( () -> new EntityDelayedFetchInitializer(
getNavigablePath(), navigablePath,
getEntityValuedModelPart().getEntityMappingType().getEntityPersister(), getEntityValuedModelPart(),
keyResult.createResultAssembler( creationState ) keyResult.createResultAssembler( creationState )
) )
); );

View File

@ -12,6 +12,8 @@ import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.internal.log.LoggingHelper; import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AbstractFetchParentAccess; import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
@ -27,7 +29,7 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess implements EntityInitializer { public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess implements EntityInitializer {
private final NavigablePath navigablePath; private final NavigablePath navigablePath;
private final EntityPersister concreteDescriptor; private final EntityValuedModelPart referencedModelPart;
private final DomainResultAssembler identifierAssembler; private final DomainResultAssembler identifierAssembler;
private Object entityInstance; private Object entityInstance;
@ -35,10 +37,10 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
public EntityDelayedFetchInitializer( public EntityDelayedFetchInitializer(
NavigablePath fetchedNavigable, NavigablePath fetchedNavigable,
EntityPersister concreteDescriptor, EntityValuedModelPart referencedModelPart,
DomainResultAssembler identifierAssembler) { DomainResultAssembler identifierAssembler) {
this.navigablePath = fetchedNavigable; this.navigablePath = fetchedNavigable;
this.concreteDescriptor = concreteDescriptor; this.referencedModelPart = referencedModelPart;
this.identifierAssembler = identifierAssembler; this.identifierAssembler = identifierAssembler;
} }
@ -52,6 +54,11 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
// nothing to do // nothing to do
} }
@Override
public ModelPart getInitializedPart(){
return referencedModelPart;
}
@Override @Override
public void resolveInstance(RowProcessingState rowProcessingState) { public void resolveInstance(RowProcessingState rowProcessingState) {
if ( entityInstance != null ) { if ( entityInstance != null ) {
@ -64,6 +71,8 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
entityInstance = null; entityInstance = null;
} }
else { else {
final EntityPersister concreteDescriptor = referencedModelPart.getEntityMappingType().getEntityPersister();
final EntityKey entityKey = new EntityKey( identifier, concreteDescriptor ); final EntityKey entityKey = new EntityKey( identifier, concreteDescriptor );
PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext(); PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext();
final Object entity = persistenceContext.getEntity( entityKey ); final Object entity = persistenceContext.getEntity( entityKey );
@ -120,7 +129,7 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
@Override @Override
public EntityPersister getEntityDescriptor() { public EntityPersister getEntityDescriptor() {
return concreteDescriptor; return referencedModelPart.getEntityMappingType().getEntityPersister();
} }
@Override @Override

View File

@ -8,6 +8,7 @@ package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
@ -49,6 +50,7 @@ public class EntityFetchJoinedImpl extends AbstractNonLazyEntityFetch {
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
return (EntityInitializer) creationState.resolveInitializer( return (EntityInitializer) creationState.resolveInitializer(
getNavigablePath(), getNavigablePath(),
getEntityValuedModelPart(),
() -> new EntityJoinedFetchInitializer( () -> new EntityJoinedFetchInitializer(
entityResult, entityResult,
getNavigablePath(), getNavigablePath(),

View File

@ -56,12 +56,14 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
public DomainResultAssembler createAssembler(FetchParentAccess parentAccess, AssemblerCreationState creationState) { public DomainResultAssembler createAssembler(FetchParentAccess parentAccess, AssemblerCreationState creationState) {
final EntityInitializer initializer = (EntityInitializer) creationState.resolveInitializer( final EntityInitializer initializer = (EntityInitializer) creationState.resolveInitializer(
getNavigablePath(), getNavigablePath(),
getFetchedMapping(),
() -> { () -> {
EntityPersister entityPersister = getReferencedMappingContainer().getEntityPersister(); EntityPersister entityPersister = getReferencedMappingContainer().getEntityPersister();
if ( selectByUniqueKey ) { if ( selectByUniqueKey ) {
return new EntitySelectFetchByUniqueKeyInitializer( return new EntitySelectFetchByUniqueKeyInitializer(
getFetchedMapping(),
(ToOneAttributeMapping) getFetchedMapping(), (ToOneAttributeMapping) getFetchedMapping(),
getNavigablePath(), getNavigablePath(),
entityPersister, entityPersister,
@ -70,6 +72,7 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
); );
} }
return new EntitySelectFetchInitializer( return new EntitySelectFetchInitializer(
getFetchedMapping(),
getNavigablePath(), getNavigablePath(),
entityPersister, entityPersister,
result.createResultAssembler( creationState ), result.createResultAssembler( creationState ),

View File

@ -70,6 +70,7 @@ public class EntityResultImpl extends AbstractEntityResultGraphNode implements E
public DomainResultAssembler createResultAssembler(AssemblerCreationState creationState) { public DomainResultAssembler createResultAssembler(AssemblerCreationState creationState) {
final EntityInitializer initializer = (EntityInitializer) creationState.resolveInitializer( final EntityInitializer initializer = (EntityInitializer) creationState.resolveInitializer(
getNavigablePath(), getNavigablePath(),
getReferencedModePart(),
() -> new EntityResultInitializer( () -> new EntityResultInitializer(
this, this,
getNavigablePath(), getNavigablePath(),

View File

@ -33,6 +33,7 @@ public class EntityResultJoinedSubclassImpl extends EntityResultImpl {
public DomainResultAssembler createResultAssembler(AssemblerCreationState creationState) { public DomainResultAssembler createResultAssembler(AssemblerCreationState creationState) {
final EntityInitializer initializer = (EntityInitializer) creationState.resolveInitializer( final EntityInitializer initializer = (EntityInitializer) creationState.resolveInitializer(
getNavigablePath(), getNavigablePath(),
getReferencedModePart(),
() -> new EntityResultInitializer( () -> new EntityResultInitializer(
this, this,
getNavigablePath(), getNavigablePath(),

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.engine.spi.EntityUniqueKey; import org.hibernate.engine.spi.EntityUniqueKey;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.persister.entity.UniqueKeyLoadable;
@ -23,12 +24,13 @@ public class EntitySelectFetchByUniqueKeyInitializer extends EntitySelectFetchIn
private final ToOneAttributeMapping fetchedAttribute; private final ToOneAttributeMapping fetchedAttribute;
public EntitySelectFetchByUniqueKeyInitializer( public EntitySelectFetchByUniqueKeyInitializer(
EntityValuedModelPart referencedModelPart,
ToOneAttributeMapping fetchedAttribute, ToOneAttributeMapping fetchedAttribute,
NavigablePath fetchedNavigable, NavigablePath fetchedNavigable,
EntityPersister concreteDescriptor, EntityPersister concreteDescriptor,
DomainResultAssembler identifierAssembler, DomainResultAssembler identifierAssembler,
boolean nullable) { boolean nullable) {
super( fetchedNavigable, concreteDescriptor, identifierAssembler, nullable ); super( referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler, nullable );
this.fetchedAttribute = fetchedAttribute; this.fetchedAttribute = fetchedAttribute;
} }

View File

@ -14,6 +14,8 @@ import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.log.LoggingHelper; import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
@ -22,6 +24,7 @@ import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.Initializer;
import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.graph.entity.EntityInitializer;
import org.hibernate.sql.results.graph.entity.EntityLoadingLogger; import org.hibernate.sql.results.graph.entity.EntityLoadingLogger;
import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable; import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
import org.hibernate.sql.results.graph.entity.LoadingEntityEntry; import org.hibernate.sql.results.graph.entity.LoadingEntityEntry;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
@ -40,9 +43,12 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
protected final EntityPersister concreteDescriptor; protected final EntityPersister concreteDescriptor;
protected final DomainResultAssembler identifierAssembler; protected final DomainResultAssembler identifierAssembler;
private final EntityValuedModelPart referencedModelPart;
protected Object entityInstance; protected Object entityInstance;
public EntitySelectFetchInitializer( public EntitySelectFetchInitializer(
EntityValuedModelPart referencedModelPart,
NavigablePath fetchedNavigable, NavigablePath fetchedNavigable,
EntityPersister concreteDescriptor, EntityPersister concreteDescriptor,
DomainResultAssembler identifierAssembler, DomainResultAssembler identifierAssembler,
@ -51,9 +57,14 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
this.concreteDescriptor = concreteDescriptor; this.concreteDescriptor = concreteDescriptor;
this.identifierAssembler = identifierAssembler; this.identifierAssembler = identifierAssembler;
this.nullable = nullable; this.nullable = nullable;
this.referencedModelPart = referencedModelPart;
this.isEnhancedForLazyLoading = concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); this.isEnhancedForLazyLoading = concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
} }
public ModelPart getInitializedPart(){
return referencedModelPart;
}
@Override @Override
public NavigablePath getNavigablePath() { public NavigablePath getNavigablePath() {
return navigablePath; return navigablePath;

View File

@ -17,6 +17,7 @@ import org.hibernate.engine.spi.BatchFetchQueue;
import org.hibernate.engine.spi.CollectionEntry; import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
@ -44,17 +45,22 @@ public class ResultsHelper {
//noinspection rawtypes //noinspection rawtypes
final List<DomainResultAssembler> assemblers = jdbcValues.getValuesMapping().resolveAssemblers( final List<DomainResultAssembler> assemblers = jdbcValues.getValuesMapping().resolveAssemblers(
new AssemblerCreationState() { new AssemblerCreationState() {
@Override @Override
public Initializer resolveInitializer( public Initializer resolveInitializer(
NavigablePath navigablePath, NavigablePath navigablePath,
ModelPart fetchedModelPart,
Supplier<Initializer> producer) { Supplier<Initializer> producer) {
final Initializer existing = initializerMap.get( navigablePath ); final Initializer existing = initializerMap.get( navigablePath );
if ( existing != null ) { if ( existing != null ) {
ResultsLogger.LOGGER.debugf( if ( fetchedModelPart.getNavigableRole().equals(
"Returning previously-registered initializer : %s", existing.getInitializedPart().getNavigableRole() ) ) {
existing ResultsLogger.LOGGER.debugf(
); "Returning previously-registered initializer : %s",
return existing; existing
);
return existing;
}
} }
final Initializer initializer = producer.get(); final Initializer initializer = producer.get();

View File

@ -11,6 +11,7 @@ import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.Association; import org.hibernate.metamodel.mapping.Association;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
@ -39,6 +40,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
*/ */
public class CircularFetchImpl implements BiDirectionalFetch, Association { public class CircularFetchImpl implements BiDirectionalFetch, Association {
private DomainResult keyResult; private DomainResult keyResult;
private EntityValuedModelPart referencedModelPart;
private final EntityMappingType entityMappingType; private final EntityMappingType entityMappingType;
private final FetchTiming timing; private final FetchTiming timing;
private final NavigablePath navigablePath; private final NavigablePath navigablePath;
@ -48,6 +50,7 @@ public class CircularFetchImpl implements BiDirectionalFetch, Association {
private final NavigablePath referencedNavigablePath; private final NavigablePath referencedNavigablePath;
public CircularFetchImpl( public CircularFetchImpl(
EntityValuedModelPart referencedModelPart,
EntityMappingType entityMappingType, EntityMappingType entityMappingType,
FetchTiming timing, FetchTiming timing,
NavigablePath navigablePath, NavigablePath navigablePath,
@ -55,6 +58,7 @@ public class CircularFetchImpl implements BiDirectionalFetch, Association {
ToOneAttributeMapping fetchable, ToOneAttributeMapping fetchable,
NavigablePath referencedNavigablePath, NavigablePath referencedNavigablePath,
DomainResult keyResult) { DomainResult keyResult) {
this.referencedModelPart = referencedModelPart;
this.entityMappingType = entityMappingType; this.entityMappingType = entityMappingType;
this.timing = timing; this.timing = timing;
this.fetchParent = fetchParent; this.fetchParent = fetchParent;
@ -98,9 +102,11 @@ public class CircularFetchImpl implements BiDirectionalFetch, Association {
final EntityInitializer initializer = (EntityInitializer) creationState.resolveInitializer( final EntityInitializer initializer = (EntityInitializer) creationState.resolveInitializer(
getNavigablePath(), getNavigablePath(),
referencedModelPart,
() -> { () -> {
if ( timing == FetchTiming.IMMEDIATE ) { if ( timing == FetchTiming.IMMEDIATE ) {
return new EntitySelectFetchInitializer( return new EntitySelectFetchInitializer(
referencedModelPart,
getReferencedPath(), getReferencedPath(),
entityMappingType.getEntityPersister(), entityMappingType.getEntityPersister(),
resultAssembler, resultAssembler,
@ -110,7 +116,7 @@ public class CircularFetchImpl implements BiDirectionalFetch, Association {
else { else {
return new EntityDelayedFetchInitializer( return new EntityDelayedFetchInitializer(
getReferencedPath(), getReferencedPath(),
(EntityPersister) ( (AttributeMapping) fetchable ).getMappedTypeDescriptor(), fetchable,
resultAssembler resultAssembler
); );
} }

View File

@ -6,7 +6,9 @@
*/ */
package org.hibernate.orm.test.entitygraph.ast; package org.hibernate.orm.test.entitygraph.ast;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -27,9 +29,11 @@ import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping; import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.hql.spi.HqlQueryImplementor; import org.hibernate.query.hql.spi.HqlQueryImplementor;
import org.hibernate.query.spi.QueryImplementor; import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.sqm.internal.QuerySqmImpl; import org.hibernate.query.sqm.internal.QuerySqmImpl;
@ -44,6 +48,7 @@ import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch; import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch;
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl; import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl;
import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.graph.entity.EntityFetch;
@ -183,8 +188,10 @@ public class CriteriaEntityGraphTest implements SessionFactoryScopeAware {
expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class ); expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class );
expectedFetchClassByAttributeName.put( "company", EntityFetchJoinedImpl.class ); expectedFetchClassByAttributeName.put( "company", EntityFetchJoinedImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) ); assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
Fetchable fetchable = getFetchable( "company", Person.class );
final Fetch companyFetch = ownerEntityResult.findFetch( "company" ); final Fetch companyFetch = ownerEntityResult.findFetch( fetchable );
List<Fetch> fetches = ownerEntityResult.getFetches();
assertThat( companyFetch, notNullValue() ); assertThat( companyFetch, notNullValue() );
final EntityResult companyEntityResult = ( (EntityFetchJoinedImpl) companyFetch).getEntityResult(); final EntityResult companyEntityResult = ( (EntityFetchJoinedImpl) companyFetch).getEntityResult();
@ -198,6 +205,19 @@ public class CriteriaEntityGraphTest implements SessionFactoryScopeAware {
); );
} }
private Fetchable getFetchable(String attributeName, Class entityClass) {
EntityPersister person = scope.getSessionFactory().getDomainModel().findEntityDescriptor(
entityClass.getName() );
Collection<AttributeMapping> attributeMappings = person.getAttributeMappings();
Fetchable fetchable = null;
for(AttributeMapping mapping :attributeMappings){
if(mapping.getAttributeName().equals( attributeName )){
fetchable = (Fetchable) mapping;
}
}
return fetchable;
}
@ParameterizedTest @ParameterizedTest
@EnumSource( GraphSemantic.class ) @EnumSource( GraphSemantic.class )
void testBasicElementCollections(GraphSemantic graphSemantic) { void testBasicElementCollections(GraphSemantic graphSemantic) {

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.orm.test.entitygraph.ast; package org.hibernate.orm.test.entitygraph.ast;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -26,6 +27,7 @@ import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.loader.ast.internal.LoaderSelectBuilder; import org.hibernate.loader.ast.internal.LoaderSelectBuilder;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping; import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
@ -38,6 +40,7 @@ import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch; import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch;
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl; import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl;
import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.graph.entity.EntityFetch;
@ -180,7 +183,8 @@ public class EntityGraphLoadPlanBuilderTest implements SessionFactoryScopeAware
expectedFetchClassByAttributeName.put( "company", EntityFetchJoinedImpl.class ); expectedFetchClassByAttributeName.put( "company", EntityFetchJoinedImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) ); assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
final Fetch companyFetch = ownerEntityResult.findFetch( "company" ); Fetchable fetchable = getFetchable( "company", Person.class );
final Fetch companyFetch = ownerEntityResult.findFetch( fetchable );
assertThat( companyFetch, notNullValue() ); assertThat( companyFetch, notNullValue() );
final EntityResult companyEntityResult = ( (EntityFetchJoinedImpl) companyFetch).getEntityResult(); final EntityResult companyEntityResult = ( (EntityFetchJoinedImpl) companyFetch).getEntityResult();
@ -194,6 +198,19 @@ public class EntityGraphLoadPlanBuilderTest implements SessionFactoryScopeAware
); );
} }
private Fetchable getFetchable(String attributeName, Class entityClass) {
EntityPersister person = scope.getSessionFactory().getDomainModel().findEntityDescriptor(
entityClass.getName() );
Collection<AttributeMapping> attributeMappings = person.getAttributeMappings();
Fetchable fetchable = null;
for(AttributeMapping mapping :attributeMappings){
if(mapping.getAttributeName().equals( attributeName )){
fetchable = (Fetchable) mapping;
}
}
return fetchable;
}
@ParameterizedTest @ParameterizedTest
@EnumSource( GraphSemantic.class ) @EnumSource( GraphSemantic.class )
void testBasicElementCollections(GraphSemantic graphSemantic) { void testBasicElementCollections(GraphSemantic graphSemantic) {

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.orm.test.entitygraph.ast; package org.hibernate.orm.test.entitygraph.ast;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -24,9 +25,11 @@ import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping; import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.hql.spi.HqlQueryImplementor; import org.hibernate.query.hql.spi.HqlQueryImplementor;
import org.hibernate.query.spi.QueryImplementor; import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.sqm.internal.QuerySqmImpl; import org.hibernate.query.sqm.internal.QuerySqmImpl;
@ -41,6 +44,7 @@ import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch; import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch;
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl; import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl;
import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.graph.entity.EntityFetch;
@ -181,7 +185,8 @@ public class HqlEntityGraphTest implements SessionFactoryScopeAware {
expectedFetchClassByAttributeName.put( "company", EntityFetchJoinedImpl.class ); expectedFetchClassByAttributeName.put( "company", EntityFetchJoinedImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) ); assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
final Fetch companyFetch = ownerEntityResult.findFetch( "company" ); Fetchable fetchable = getFetchable( "company", Person.class );
final Fetch companyFetch = ownerEntityResult.findFetch( fetchable );
assertThat( companyFetch, notNullValue() ); assertThat( companyFetch, notNullValue() );
final EntityResult companyEntityResult = ( (EntityFetchJoinedImpl) companyFetch).getEntityResult(); final EntityResult companyEntityResult = ( (EntityFetchJoinedImpl) companyFetch).getEntityResult();
@ -195,6 +200,19 @@ public class HqlEntityGraphTest implements SessionFactoryScopeAware {
); );
} }
private Fetchable getFetchable(String attributeName, Class entityClass) {
EntityPersister person = scope.getSessionFactory().getDomainModel().findEntityDescriptor(
entityClass.getName() );
Collection<AttributeMapping> attributeMappings = person.getAttributeMappings();
Fetchable fetchable = null;
for(AttributeMapping mapping :attributeMappings){
if(mapping.getAttributeName().equals( attributeName )){
fetchable = (Fetchable) mapping;
}
}
return fetchable;
}
@ParameterizedTest @ParameterizedTest
@EnumSource( GraphSemantic.class ) @EnumSource( GraphSemantic.class )
void testBasicElementCollections(GraphSemantic graphSemantic) { void testBasicElementCollections(GraphSemantic graphSemantic) {

View File

@ -10,6 +10,7 @@ import java.io.Serializable;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue; import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Inheritance; import javax.persistence.Inheritance;
import javax.persistence.InheritanceType; import javax.persistence.InheritanceType;
@ -17,6 +18,8 @@ import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
@ -25,6 +28,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ -49,8 +53,8 @@ public class MultiSingleTableLoadTest {
@BeforeEach @BeforeEach
public void createTestData(SessionFactoryScope scope) { public void createTestData(SessionFactoryScope scope) {
scope.inTransaction( session -> { scope.inTransaction( session -> {
Holder holder1 = new Holder( 1, new B( 1, new Y( 1 ) ) ); Holder holder1 = new Holder( 1, new B( 1, new Y( 1, "y" ) ) );
Holder holder2 = new Holder( 2, new C( 2, new Z( 2 ) ) ); Holder holder2 = new Holder( 2, new C( 2, new Z( 2, "z" ) ) );
session.persist( holder1 ); session.persist( holder1 );
session.persist( holder2 ); session.persist( holder2 );
@ -76,7 +80,22 @@ public class MultiSingleTableLoadTest {
Holder task1 = session.find( Holder.class, 1L ); Holder task1 = session.find( Holder.class, 1L );
Holder task2 = session.find( Holder.class, 2L ); Holder task2 = session.find( Holder.class, 2L );
assertNotNull( task1 ); assertNotNull( task1 );
A task1A = task1.getA();
assertTrue( task1A instanceof B );
B b = (B) task1A;
assertTrue( b.getX() instanceof Y );
assertTrue( Hibernate.isInitialized( b.getX() ) );
assertEquals( "y", b.getX().getTheString() );
assertNotNull( task2 ); assertNotNull( task2 );
A task2A = task2.getA();
assertTrue( task2A instanceof C );
C c = (C) task2A;
assertTrue( c.getX() instanceof Z );
assertTrue( Hibernate.isInitialized( c.getX() ) );
Z z = (Z) c.getX();
assertEquals( "z", z.getTheString() );
} ); } );
} }
@ -111,6 +130,10 @@ public class MultiSingleTableLoadTest {
this.id = id; this.id = id;
this.a = a; this.a = a;
} }
public A getA() {
return a;
}
} }
@Entity(name = "A") @Entity(name = "A")
@ -131,7 +154,7 @@ public class MultiSingleTableLoadTest {
@Entity(name = "B") @Entity(name = "B")
@DiscriminatorValue("B") @DiscriminatorValue("B")
public static class B extends A { public static class B extends A {
@ManyToOne(optional = true, cascade = CascadeType.ALL) @ManyToOne(optional = true, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "x_id") @JoinColumn(name = "x_id")
private Y x; private Y x;
@ -142,6 +165,10 @@ public class MultiSingleTableLoadTest {
super( id ); super( id );
this.x = x; this.x = x;
} }
public Y getX() {
return x;
}
} }
@Entity(name = "C") @Entity(name = "C")
@ -158,6 +185,10 @@ public class MultiSingleTableLoadTest {
super( id ); super( id );
this.x = x; this.x = x;
} }
public X getX() {
return x;
}
} }
@Entity(name = "X") @Entity(name = "X")
@ -178,22 +209,36 @@ public class MultiSingleTableLoadTest {
@Entity(name = "Y") @Entity(name = "Y")
@DiscriminatorValue("Y") @DiscriminatorValue("Y")
public static class Y extends X { public static class Y extends X {
private String theString;
public Y() { public Y() {
} }
public Y(long id) { public Y(long id, String theString) {
super( id ); super( id );
this.theString = theString;
}
public String getTheString() {
return theString;
} }
} }
@Entity(name = "Z") @Entity(name = "Z")
@DiscriminatorValue("Z") @DiscriminatorValue("Z")
public static class Z extends X { public static class Z extends X {
private String theString;
public Z() { public Z() {
} }
public Z(long id) { public Z(long id, String theString) {
super( id ); super( id );
this.theString = theString;
}
public String getTheString() {
return theString;
} }
} }
} }

View File

@ -0,0 +1,53 @@
/*
* 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.inheritance.discriminator;
import org.hibernate.Session;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.RequiresDialects;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.test.inheritance.discriminator.InheritingEntity;
import org.hibernate.test.inheritance.discriminator.ParentEntity;
import org.junit.jupiter.api.Test;
/**
* @author Pawel Stawicki
*/
@RequiresDialects(value = {
@RequiresDialect(value = PostgreSQL81Dialect.class), @RequiresDialect(value = PostgreSQLDialect.class)
})
@DomainModel(annotatedClasses = {
ParentEntity.class, InheritingEntity.class
})
@TestForIssue(jiraKey = "HHH-6580")
public class PersistChildEntitiesWithDiscriminatorTest {
@Test
public void doIt(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
// we need the 2 inserts so that the id is incremented on the second get-generated-keys-result set, since
// on the first insert both the pk and the discriminator values are 1
session.save( new InheritingEntity( "yabba" ) );
session.save( new InheritingEntity( "dabba" ) );
}
);
scope.inTransaction(
session -> {
session.createQuery( "delete ParentEntity" ).executeUpdate();
}
);
}
}

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.inheritance.discriminator; package org.hibernate.orm.test.inheritance.discriminator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -22,20 +22,31 @@ import javax.persistence.OneToMany;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.orm.junit.DomainModel;
import org.junit.Before; import org.hibernate.testing.orm.junit.SessionFactory;
import org.junit.Test; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is; import static org.hamcrest.core.Is.is;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
/** /**
* @author Davide D'Alto * @author Davide D'Alto
*/ */
@TestForIssue( jiraKey = "HHH-12332") @TestForIssue(jiraKey = "HHH-12332")
public class SingleTableInheritancePersistTest extends BaseCoreFunctionalTestCase { @DomainModel(
annotatedClasses = {
SingleTableInheritancePersistTest.Family.class,
SingleTableInheritancePersistTest.Person.class,
SingleTableInheritancePersistTest.Child.class,
SingleTableInheritancePersistTest.Man.class,
SingleTableInheritancePersistTest.Woman.class
}
)
@SessionFactory
public class SingleTableInheritancePersistTest {
private final Man john = new Man( "John", "Riding Roller Coasters" ); private final Man john = new Man( "John", "Riding Roller Coasters" );
private final Woman jane = new Woman( "Jane", "Hippotherapist" ); private final Woman jane = new Woman( "Jane", "Hippotherapist" );
@ -45,66 +56,57 @@ public class SingleTableInheritancePersistTest extends BaseCoreFunctionalTestCas
private final List<Child> children = new ArrayList<>( Arrays.asList( susan, mark ) ); private final List<Child> children = new ArrayList<>( Arrays.asList( susan, mark ) );
private final List<Person> familyMembers = Arrays.asList( john, jane, susan, mark ); private final List<Person> familyMembers = Arrays.asList( john, jane, susan, mark );
@Override @BeforeEach
protected Class<?>[] getAnnotatedClasses() { public void setUp(SessionFactoryScope scope) {
return new Class[] { scope.inTransaction(
Family.class, session -> {
Person.class, jane.setHusband( john );
Child.class, jane.setChildren( children );
Man.class,
Woman.class
};
}
@Before john.setWife( jane );
public void setUp() { john.setChildren( children );
doInHibernate( this::sessionFactory, session -> {
jane.setHusband( john );
jane.setChildren( children );
john.setWife( jane ); for ( Child child : children ) {
john.setChildren( children ); child.setFather( john );
child.setMother( jane );
}
for ( Child child : children ) { for ( Person person : familyMembers ) {
child.setFather( john ); family.add( person );
child.setMother( jane ); }
}
for ( Person person : familyMembers ) { session.persist( family );
family.add( person ); } );
}
session.persist( family );
} );
} }
@Test @Test
public void testPolymorphicAssociation() { public void testPolymorphicAssociation(SessionFactoryScope scope) {
doInHibernate( this::sessionFactory, session1 -> { scope.inTransaction(
Family family = session1.createQuery( "FROM Family f", Family.class ).getSingleResult(); session -> {
List<Person> members = family.getMembers(); Family family = session.createQuery( "FROM Family f", Family.class ).getSingleResult();
assertThat( members.size(), is( familyMembers.size() ) ); List<Person> members = family.getMembers();
for ( Person person : members ) { assertThat( members.size(), is( familyMembers.size() ) );
if ( person instanceof Man ) { for ( Person person : members ) {
assertThat( ( (Man) person ).getHobby(), is( john.getHobby() ) ); if ( person instanceof Man ) {
} assertThat( ( (Man) person ).getHobby(), is( john.getHobby() ) );
else if ( person instanceof Woman ) { }
assertThat( ( (Woman) person ).getJob(), is( jane.getJob() ) ); else if ( person instanceof Woman ) {
} assertThat( ( (Woman) person ).getJob(), is( jane.getJob() ) );
else if ( person instanceof Child ) { }
if ( person.getName().equals( "Susan" ) ) { else if ( person instanceof Child ) {
assertThat( ( (Child) person ).getFavouriteToy(), is( susan.getFavouriteToy() ) ); if ( person.getName().equals( "Susan" ) ) {
assertThat( ( (Child) person ).getFavouriteToy(), is( susan.getFavouriteToy() ) );
}
else {
assertThat( ( (Child) person ).getFavouriteToy(), is( mark.getFavouriteToy() ) );
}
}
else {
fail( "Unexpected result: " + person );
}
} }
else { } );
assertThat( ( (Child) person ).getFavouriteToy(), is( mark.getFavouriteToy() ) );
}
}
else {
fail( "Unexpected result: " + person );
}
}
} );
} }
@Entity(name = "Family") @Entity(name = "Family")

View File

@ -1,45 +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.test.inheritance.discriminator;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
/**
* @author Pawel Stawicki
*/
@RequiresDialect( value = {PostgreSQL81Dialect.class, PostgreSQLDialect.class}, jiraKey = "HHH-6580" )
public class PersistChildEntitiesWithDiscriminatorTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { ParentEntity.class, InheritingEntity.class };
}
@Test
public void doIt() {
Session session = openSession();
session.beginTransaction();
// we need the 2 inserts so that the id is incremented on the second get-generated-keys-result set, since
// on the first insert both the pk and the discriminator values are 1
session.save( new InheritingEntity( "yabba" ) );
session.save( new InheritingEntity( "dabba" ) );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
session.createQuery( "delete ParentEntity" ).executeUpdate();
session.getTransaction().commit();
session.close();
}
}