HHH-16282 Make it possible for Hibernate Reactive to plug in custom fetch initializers
This commit is contained in:
parent
ff19a9124f
commit
06e24bd420
|
@ -157,6 +157,33 @@ public class ToOneAttributeMapping
|
|||
private String identifyingColumnsTableExpression;
|
||||
private boolean canUseParentTableGroup;
|
||||
|
||||
protected ToOneAttributeMapping(ToOneAttributeMapping delegate) {
|
||||
super(
|
||||
delegate.getAttributeName(),
|
||||
delegate.getStateArrayPosition(),
|
||||
delegate.getFetchableKey(),
|
||||
delegate.getAttributeMetadata(),
|
||||
delegate.getMappedFetchOptions(),
|
||||
delegate.getDeclaringType(),
|
||||
delegate.getPropertyAccess()
|
||||
);
|
||||
navigableRole = delegate.navigableRole;
|
||||
isInternalLoadNullable = delegate.isInternalLoadNullable;
|
||||
notFoundAction = delegate.notFoundAction;
|
||||
unwrapProxy = delegate.unwrapProxy;
|
||||
isOptional = delegate.isOptional;
|
||||
entityMappingType = delegate.entityMappingType;
|
||||
referencedPropertyName = delegate.referencedPropertyName;
|
||||
targetKeyPropertyName = delegate.targetKeyPropertyName;
|
||||
cardinality = delegate.cardinality;
|
||||
bidirectionalAttributePath = delegate.bidirectionalAttributePath;
|
||||
declaringTableGroupProducer = delegate.declaringTableGroupProducer;
|
||||
isKeyTableNullable = delegate.isKeyTableNullable;
|
||||
sqlAliasStem = delegate.sqlAliasStem;
|
||||
targetKeyPropertyNames = delegate.targetKeyPropertyNames;
|
||||
isNullable = delegate.isNullable;
|
||||
foreignKeyDescriptor = delegate.foreignKeyDescriptor;
|
||||
}
|
||||
|
||||
public ToOneAttributeMapping(
|
||||
String name,
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.sql.results.graph.Fetch;
|
|||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.Initializer;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
|
||||
|
@ -69,12 +70,20 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab
|
|||
lhsTableGroup.addTableGroupJoin( tableGroupJoin );
|
||||
return tableGroupJoin.getJoinedGroup();
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
afterInitialize( this, creationState );
|
||||
}
|
||||
|
||||
// For Hibernate Reactive
|
||||
protected EmbeddableFetchImpl(EmbeddableFetchImpl original) {
|
||||
super( original.getFetchContainer(), original.getNavigablePath() );
|
||||
fetchParent = original.fetchParent;
|
||||
fetchTiming = original.fetchTiming;
|
||||
tableGroup = original.tableGroup;
|
||||
hasTableGroup = original.hasTableGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchTiming getTiming() {
|
||||
return fetchTiming;
|
||||
|
@ -133,11 +142,7 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab
|
|||
final EmbeddableInitializer initializer = creationState.resolveInitializer(
|
||||
getNavigablePath(),
|
||||
getReferencedModePart(),
|
||||
() -> new EmbeddableFetchInitializer(
|
||||
parentAccess,
|
||||
this,
|
||||
creationState
|
||||
)
|
||||
() -> buildEmbeddableFetchInitializer( parentAccess, this, creationState )
|
||||
).asEmbeddableInitializer();
|
||||
|
||||
assert initializer != null;
|
||||
|
@ -145,6 +150,13 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab
|
|||
return new EmbeddableAssembler( initializer );
|
||||
}
|
||||
|
||||
protected Initializer buildEmbeddableFetchInitializer(
|
||||
FetchParentAccess parentAccess,
|
||||
EmbeddableResultGraphNode embeddableFetch,
|
||||
AssemblerCreationState creationState) {
|
||||
return new EmbeddableFetchInitializer( parentAccess, this, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(GraphImplementor graphImplementor) {
|
||||
return getFetchParent().appliesTo( graphImplementor );
|
||||
|
|
|
@ -213,10 +213,18 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
return navigablePath;
|
||||
}
|
||||
|
||||
protected DomainResultAssembler<?> getIdentifierAssembler() {
|
||||
return identifierAssembler;
|
||||
}
|
||||
|
||||
protected boolean isMissing() {
|
||||
return missing;
|
||||
}
|
||||
|
||||
protected void setMissing(boolean missing) {
|
||||
this.missing = missing;
|
||||
}
|
||||
|
||||
protected abstract boolean isEntityReturn();
|
||||
|
||||
@Override
|
||||
|
@ -1138,6 +1146,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
return lockMode;
|
||||
}
|
||||
|
||||
protected DomainResultAssembler<?>[][] getAssemblers() {
|
||||
return assemblers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishUpRow(RowProcessingState rowProcessingState) {
|
||||
final SharedSessionContractImplementor session = rowProcessingState.getSession();
|
||||
|
|
|
@ -68,6 +68,10 @@ public abstract class AbstractNonLazyEntityFetch extends AbstractFetchParent imp
|
|||
FetchParentAccess parentAccess,
|
||||
AssemblerCreationState creationState) {
|
||||
final EntityInitializer entityInitializer = getEntityInitializer( parentAccess, creationState );
|
||||
return buildEntityAssembler( entityInitializer );
|
||||
}
|
||||
|
||||
protected EntityAssembler buildEntityAssembler(EntityInitializer entityInitializer) {
|
||||
return new EntityAssembler( getFetchedMapping().getJavaType(), entityInitializer );
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler;
|
|||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.Initializer;
|
||||
import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
|
@ -58,7 +57,7 @@ public class EntityDelayedFetchImpl extends AbstractNonJoinedEntityFetch {
|
|||
final Initializer entityInitializer = creationState.resolveInitializer(
|
||||
navigablePath,
|
||||
getEntityValuedModelPart(),
|
||||
() -> new EntityDelayedFetchInitializer(
|
||||
() -> buildEntityDelayedFetchInitializer(
|
||||
parentAccess,
|
||||
navigablePath,
|
||||
(ToOneAttributeMapping) getEntityValuedModelPart(),
|
||||
|
@ -67,6 +66,20 @@ public class EntityDelayedFetchImpl extends AbstractNonJoinedEntityFetch {
|
|||
)
|
||||
);
|
||||
|
||||
return buildEntityAssembler( entityInitializer );
|
||||
}
|
||||
|
||||
protected EntityAssembler buildEntityAssembler(Initializer entityInitializer) {
|
||||
return new EntityAssembler( getFetchedMapping().getJavaType(), entityInitializer.asEntityInitializer() );
|
||||
}
|
||||
|
||||
protected Initializer buildEntityDelayedFetchInitializer(FetchParentAccess parentAccess, NavigablePath navigablePath, ToOneAttributeMapping entityValuedModelPart, boolean selectByUniqueKey, DomainResultAssembler<?> resultAssembler) {
|
||||
return new EntityDelayedFetchInitializer(
|
||||
parentAccess,
|
||||
navigablePath,
|
||||
entityValuedModelPart,
|
||||
selectByUniqueKey,
|
||||
resultAssembler
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,14 +183,14 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
|
|||
}
|
||||
}
|
||||
|
||||
private EntityInitializer getParentEntityInitializer(FetchParentAccess parentAccess) {
|
||||
protected EntityInitializer getParentEntityInitializer(FetchParentAccess parentAccess) {
|
||||
if ( parentAccess != null ) {
|
||||
return parentAccess.findFirstEntityInitializer();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isEnhancedForLazyLoading(EntityInitializer parentEntityIntialiazer) {
|
||||
protected static boolean isEnhancedForLazyLoading(EntityInitializer parentEntityIntialiazer) {
|
||||
return parentEntityIntialiazer != null && parentEntityIntialiazer.getEntityDescriptor()
|
||||
.getBytecodeEnhancementMetadata()
|
||||
.isEnhancedForLazyLoading();
|
||||
|
@ -219,6 +219,10 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
|
|||
return entityInstance;
|
||||
}
|
||||
|
||||
protected void setEntityInstance(Object entityInstance) {
|
||||
this.entityInstance = entityInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityKey getEntityKey() {
|
||||
throw new UnsupportedOperationException();
|
||||
|
@ -259,4 +263,19 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
|
|||
return "EntityDelayedFetchInitializer(" + LoggingHelper.toLoggableString( navigablePath ) + ")";
|
||||
}
|
||||
|
||||
protected Object getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
protected void setIdentifier(Object identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
protected boolean isSelectByUniqueKey() {
|
||||
return selectByUniqueKey;
|
||||
}
|
||||
|
||||
protected DomainResultAssembler<?> getIdentifierAssembler() {
|
||||
return identifierAssembler;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler;
|
|||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.Initializer;
|
||||
import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
|
@ -68,18 +67,33 @@ public class EntityDelayedResultImpl implements DomainResult {
|
|||
final Initializer initializer = creationState.resolveInitializer(
|
||||
getNavigablePath(),
|
||||
entityValuedModelPart,
|
||||
() -> new EntityDelayedFetchInitializer(
|
||||
null,
|
||||
() -> buildEntityDelayedFetchInitializer(
|
||||
getNavigablePath(),
|
||||
(ToOneAttributeMapping) entityValuedModelPart,
|
||||
false,
|
||||
identifierResult.createResultAssembler( parentAccess, creationState )
|
||||
)
|
||||
);
|
||||
|
||||
return buildEntityAssembler( initializer );
|
||||
}
|
||||
|
||||
protected EntityAssembler buildEntityAssembler(Initializer initializer) {
|
||||
return new EntityAssembler( getResultJavaType(), initializer.asEntityInitializer() );
|
||||
}
|
||||
|
||||
protected Initializer buildEntityDelayedFetchInitializer(
|
||||
NavigablePath navigablePath,
|
||||
ToOneAttributeMapping entityValuedModelPart,
|
||||
DomainResultAssembler resultAssembler) {
|
||||
return new EntityDelayedFetchInitializer(
|
||||
null,
|
||||
navigablePath,
|
||||
(ToOneAttributeMapping) entityValuedModelPart,
|
||||
false,
|
||||
resultAssembler
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EntityDelayedResultImpl {" + getNavigablePath() + "}";
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.sql.results.graph.entity.internal;
|
|||
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
|
@ -37,6 +38,14 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
|
|||
|
||||
this.keyResult = keyResult;
|
||||
this.selectByUniqueKey = selectByUniqueKey;
|
||||
|
||||
}
|
||||
|
||||
// For Hibernate Reactive
|
||||
protected EntityFetchSelectImpl(EntityFetchSelectImpl original) {
|
||||
super( original.getNavigablePath(), original.getFetchedMapping(), original.getFetchParent() );
|
||||
this.keyResult = original.keyResult;
|
||||
this.selectByUniqueKey = original.selectByUniqueKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,18 +65,40 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
|
|||
final Initializer initializer = creationState.resolveInitializer(
|
||||
getNavigablePath(),
|
||||
getFetchedMapping(),
|
||||
() ->
|
||||
EntitySelectFetchInitializerBuilder.createInitializer(
|
||||
parentAccess,
|
||||
(ToOneAttributeMapping) getFetchedMapping(),
|
||||
getReferencedMappingContainer().getEntityPersister(),
|
||||
keyResult,
|
||||
getNavigablePath(),
|
||||
selectByUniqueKey,
|
||||
creationState
|
||||
)
|
||||
() -> buildEntitySelectFetchInitializer(
|
||||
parentAccess,
|
||||
(ToOneAttributeMapping) getFetchedMapping(),
|
||||
getReferencedMappingContainer().getEntityPersister(),
|
||||
keyResult,
|
||||
getNavigablePath(),
|
||||
selectByUniqueKey,
|
||||
creationState
|
||||
)
|
||||
);
|
||||
|
||||
return buildEntityAssembler( initializer );
|
||||
}
|
||||
|
||||
protected Initializer buildEntitySelectFetchInitializer(
|
||||
FetchParentAccess parentAccess,
|
||||
ToOneAttributeMapping fetchedMapping,
|
||||
EntityPersister entityPersister,
|
||||
DomainResult<?> keyResult,
|
||||
NavigablePath navigablePath,
|
||||
boolean selectByUniqueKey,
|
||||
AssemblerCreationState creationState) {
|
||||
return EntitySelectFetchInitializerBuilder.createInitializer(
|
||||
parentAccess,
|
||||
fetchedMapping,
|
||||
entityPersister,
|
||||
keyResult,
|
||||
navigablePath,
|
||||
selectByUniqueKey,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
||||
protected DomainResultAssembler<?> buildEntityAssembler(Initializer initializer) {
|
||||
return new EntityAssembler( getResultJavaType(), initializer.asEntityInitializer() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.sql.results.internal.domain;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.BiDirectionalFetch;
|
||||
|
@ -59,7 +60,18 @@ public class CircularFetchImpl implements BiDirectionalFetch {
|
|||
this.referencedNavigablePath = referencedNavigablePath;
|
||||
this.fetchable = fetchable;
|
||||
this.keyResult = keyResult;
|
||||
}
|
||||
|
||||
protected CircularFetchImpl(CircularFetchImpl original) {
|
||||
this.referencedModelPart = original.referencedModelPart;
|
||||
this.entityMappingType = original.entityMappingType;
|
||||
this.timing = original.timing;
|
||||
this.fetchParent = original.fetchParent;
|
||||
this.navigablePath = original.navigablePath;
|
||||
this.selectByUniqueKey = original.selectByUniqueKey;
|
||||
this.referencedNavigablePath = original.referencedNavigablePath;
|
||||
this.fetchable = original.fetchable;
|
||||
this.keyResult = original.keyResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -95,28 +107,7 @@ public class CircularFetchImpl implements BiDirectionalFetch {
|
|||
final Initializer initializer = creationState.resolveInitializer(
|
||||
getNavigablePath(),
|
||||
referencedModelPart,
|
||||
() -> {
|
||||
if ( timing == FetchTiming.IMMEDIATE ) {
|
||||
return EntitySelectFetchInitializerBuilder.createInitializer(
|
||||
parentAccess,
|
||||
fetchable,
|
||||
entityMappingType.getEntityPersister(),
|
||||
keyResult,
|
||||
getNavigablePath(),
|
||||
selectByUniqueKey,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
else {
|
||||
return new EntityDelayedFetchInitializer(
|
||||
parentAccess,
|
||||
getReferencedPath(),
|
||||
fetchable,
|
||||
selectByUniqueKey,
|
||||
keyResult.createResultAssembler( parentAccess, creationState )
|
||||
);
|
||||
}
|
||||
}
|
||||
() -> initializerFactory( parentAccess, creationState )
|
||||
);
|
||||
|
||||
return new BiDirectionalFetchAssembler(
|
||||
|
@ -125,39 +116,96 @@ public class CircularFetchImpl implements BiDirectionalFetch {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public FetchTiming getTiming() {
|
||||
return timing;
|
||||
protected Initializer initializerFactory(FetchParentAccess parentAccess, AssemblerCreationState creationState) {
|
||||
if ( timing == FetchTiming.IMMEDIATE ) {
|
||||
return buildEntitySelectFetchInitializer(
|
||||
parentAccess,
|
||||
fetchable,
|
||||
entityMappingType.getEntityPersister(),
|
||||
keyResult,
|
||||
getNavigablePath(),
|
||||
selectByUniqueKey,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
else {
|
||||
return buildEntityDelayedFetchInitializer(
|
||||
parentAccess,
|
||||
getReferencedPath(),
|
||||
fetchable,
|
||||
selectByUniqueKey,
|
||||
keyResult.createResultAssembler( parentAccess, creationState )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTableGroup() {
|
||||
return true;
|
||||
protected Initializer buildEntitySelectFetchInitializer(
|
||||
FetchParentAccess parentAccess,
|
||||
ToOneAttributeMapping fetchable,
|
||||
EntityPersister entityPersister,
|
||||
DomainResult<?> keyResult,
|
||||
NavigablePath navigablePath,
|
||||
boolean selectByUniqueKey,
|
||||
AssemblerCreationState creationState) {
|
||||
return EntitySelectFetchInitializerBuilder
|
||||
.createInitializer(
|
||||
parentAccess,
|
||||
this.fetchable,
|
||||
entityPersister,
|
||||
keyResult,
|
||||
navigablePath,
|
||||
selectByUniqueKey,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
||||
private static class BiDirectionalFetchAssembler implements DomainResultAssembler {
|
||||
private EntityInitializer initializer;
|
||||
private JavaType assembledJavaType;
|
||||
protected Initializer buildEntityDelayedFetchInitializer(
|
||||
FetchParentAccess parentAccess,
|
||||
NavigablePath referencedPath,
|
||||
ToOneAttributeMapping fetchable,
|
||||
boolean selectByUniqueKey,
|
||||
DomainResultAssembler<?> resultAssembler) {
|
||||
return new EntityDelayedFetchInitializer(
|
||||
parentAccess,
|
||||
referencedPath,
|
||||
fetchable,
|
||||
selectByUniqueKey,
|
||||
resultAssembler
|
||||
);
|
||||
}
|
||||
|
||||
public BiDirectionalFetchAssembler(
|
||||
EntityInitializer initializer,
|
||||
JavaType assembledJavaType) {
|
||||
this.initializer = initializer;
|
||||
this.assembledJavaType = assembledJavaType;
|
||||
|
||||
@Override
|
||||
public FetchTiming getTiming ( ) {
|
||||
return timing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
|
||||
initializer.resolveInstance( rowProcessingState );
|
||||
return initializer.getInitializedInstance();
|
||||
public boolean hasTableGroup ( ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getAssembledJavaType() {
|
||||
return assembledJavaType;
|
||||
private static class BiDirectionalFetchAssembler implements DomainResultAssembler {
|
||||
private EntityInitializer initializer;
|
||||
private JavaType assembledJavaType;
|
||||
|
||||
public BiDirectionalFetchAssembler(
|
||||
EntityInitializer initializer,
|
||||
JavaType assembledJavaType) {
|
||||
this.initializer = initializer;
|
||||
this.assembledJavaType = assembledJavaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
|
||||
initializer.resolveInstance( rowProcessingState );
|
||||
return initializer.getInitializedInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType getAssembledJavaType() {
|
||||
return assembledJavaType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue