Work on column alias resolving
This commit is contained in:
parent
6643e9f4bc
commit
7bf5117a02
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Hibernate often deals with compound names/paths. This interface defines a standard way of interacting with them
|
||||
*
|
||||
|
@ -21,4 +23,15 @@ public interface DotIdentifierSequence {
|
|||
default boolean isRoot() {
|
||||
return getParent() == null;
|
||||
}
|
||||
|
||||
default <T> T resolve(T base, BiFunction<T, String, T> resolver) {
|
||||
final T result;
|
||||
if ( getParent() == null ) {
|
||||
result = base;
|
||||
}
|
||||
else {
|
||||
result = resolver.apply( getParent().resolve( base, resolver ), getLocalName() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,11 +26,14 @@ import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType;
|
|||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmResultSetMappingType;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.internal.FetchMementoBasicStandard;
|
||||
import org.hibernate.query.internal.FetchMementoHbmStandard;
|
||||
import org.hibernate.query.internal.FetchMementoHbmStandard.FetchParentMemento;
|
||||
import org.hibernate.query.internal.ModelPartResultMementoBasicImpl;
|
||||
|
@ -538,9 +541,10 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
|||
);
|
||||
}
|
||||
navigablePath = fetchParentMemento.getNavigablePath().append( propertyPathParts[ i ] );
|
||||
fetchable = (Fetchable) ( (FetchableContainer) fetchable ).findSubPart( propertyPathParts[i], null );
|
||||
}
|
||||
|
||||
return new FetchMementoHbmStandard( navigablePath, fetchParentMemento, fetchable );
|
||||
return new FetchMementoBasicStandard( navigablePath, (BasicValuedModelPart) fetchable, columnAliases.get( 0 ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
|||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.internal.FetchMementoJpa;
|
||||
import org.hibernate.query.internal.FetchMementoBasicStandard;
|
||||
import org.hibernate.query.internal.ModelPartResultMementoBasicImpl;
|
||||
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl;
|
||||
import org.hibernate.query.internal.ResultMementoBasicStandard;
|
||||
|
@ -41,6 +41,7 @@ import org.hibernate.query.named.NamedResultSetMappingMemento;
|
|||
import org.hibernate.query.named.ResultMemento;
|
||||
import org.hibernate.query.named.ResultMementoBasic;
|
||||
import org.hibernate.query.named.ResultMementoInstantiation.ArgumentMemento;
|
||||
import org.hibernate.query.results.complete.CompleteResultBuilderBasicModelPart;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
|
@ -395,7 +396,20 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
|||
|
||||
@Override
|
||||
public FetchMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
|
||||
return new FetchMementoJpa( navigablePath, relativeFetchPath );
|
||||
final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels();
|
||||
final EntityMappingType entityMapping = runtimeMetamodels.getEntityMappingType( entityName );
|
||||
|
||||
final ModelPart subPart = entityMapping.resolveSubPart( navigablePath );
|
||||
if ( subPart instanceof BasicValuedModelPart ) {
|
||||
assert columnNames.size() == 1;
|
||||
final BasicValuedModelPart basicPart = (BasicValuedModelPart) subPart;
|
||||
|
||||
return new FetchMementoBasicStandard( navigablePath, basicPart, columnNames.get( 0 ) );
|
||||
}
|
||||
throw new NotYetImplementedFor6Exception(
|
||||
"Only support for basic-valued model-parts have been implemented : " + relativeFetchPath
|
||||
+ " [" + subPart + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.metamodel.mapping;
|
|||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.DotIdentifierSequence;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
|
||||
/**
|
||||
|
@ -33,6 +34,10 @@ public interface Queryable extends ModelPart {
|
|||
*/
|
||||
ModelPart findSubPart(String name, EntityMappingType treatTargetType);
|
||||
|
||||
default ModelPart resolveSubPart(DotIdentifierSequence path) {
|
||||
return path.resolve( (ModelPart) this, (part, name) -> ( (Queryable) part ).findSubPart( name, null ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* For an entity, this form allows for Hibernate's "implicit treat" support -
|
||||
* meaning it should find a sub-part whether defined on the entity or one of its sub-types.
|
||||
|
|
|
@ -219,6 +219,7 @@ import org.hibernate.sql.ast.tree.predicate.Predicate;
|
|||
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.FetchableContainer;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
import org.hibernate.tuple.GenerationTiming;
|
||||
|
@ -6751,11 +6752,14 @@ public abstract class AbstractEntityPersister
|
|||
public void visitKeyFetchables(
|
||||
Consumer<Fetchable> fetchableConsumer,
|
||||
EntityMappingType treatTargetType) {
|
||||
// if ( getIdentifierMapping() instanceof FetchableContainer ) {
|
||||
// final EntityIdentifierMapping identifierMapping = getIdentifierMapping();
|
||||
// if ( identifierMapping instanceof FetchableContainer ) {
|
||||
// // essentially means the entity has a composite id - ask the embeddable to visit its fetchables
|
||||
// ( (FetchableContainer) getIdentifierMapping() ).visitFetchables( fetchableConsumer, treatTargetType );
|
||||
// ( (FetchableContainer) identifierMapping ).visitFetchables( fetchableConsumer, treatTargetType );
|
||||
// }
|
||||
// else {
|
||||
// fetchableConsumer.accept( (Fetchable) identifierMapping );
|
||||
// }
|
||||
// otherwise, nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,58 +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.query.internal;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
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.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class FetchBuilderJpa implements FetchBuilder {
|
||||
private final NavigablePath navigablePath;
|
||||
private final String attributePath;
|
||||
|
||||
public FetchBuilderJpa(NavigablePath navigablePath, String attributePath) {
|
||||
this.navigablePath = navigablePath;
|
||||
this.attributePath = attributePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
NavigablePath fetchPath,
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
assert fetchPath.equals( navigablePath );
|
||||
assert fetchPath.getFullPath().endsWith( attributePath );
|
||||
|
||||
final FetchableContainer container = parent.getReferencedMappingContainer();
|
||||
final Fetchable subPart = (Fetchable) container.findSubPart( fetchPath.getLocalName(), null );
|
||||
return subPart.generateFetch(
|
||||
parent,
|
||||
fetchPath,
|
||||
FetchTiming.IMMEDIATE,
|
||||
true,
|
||||
LockMode.READ,
|
||||
null,
|
||||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,49 +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.query.internal;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.named.FetchMemento;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class FetchMementoJpa implements FetchMemento {
|
||||
|
||||
private final NavigablePath fetchPath;
|
||||
private final String attributePath;
|
||||
|
||||
public FetchMementoJpa(NavigablePath fetchPath, String attributePath) {
|
||||
this.fetchPath = fetchPath;
|
||||
this.attributePath = attributePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder resolve(
|
||||
Parent parent,
|
||||
Consumer<String> querySpaceConsumer,
|
||||
ResultSetMappingResolutionContext context) {
|
||||
final String[] names = attributePath.split( "\\." );
|
||||
|
||||
NavigablePath fetchPath = parent.getNavigablePath();
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for ( int i = 0; i < names.length; i++ ) {
|
||||
fetchPath = fetchPath.append( names[ i ] );
|
||||
}
|
||||
|
||||
return new FetchBuilderJpa( fetchPath, attributePath );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return fetchPath;
|
||||
}
|
||||
|
||||
}
|
|
@ -34,6 +34,7 @@ import org.hibernate.query.results.implicit.ImplicitFetchBuilder;
|
|||
import org.hibernate.query.results.implicit.ImplicitFetchBuilderBasic;
|
||||
import org.hibernate.query.results.implicit.ImplicitFetchBuilderEmbeddable;
|
||||
import org.hibernate.query.results.implicit.ImplicitModelPartResultBuilderEntity;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
|
||||
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
|
||||
|
@ -243,7 +244,10 @@ public class Builders {
|
|||
return new ImplicitModelPartResultBuilderEntity( entityMappingType );
|
||||
}
|
||||
|
||||
public static ImplicitFetchBuilder implicitFetchBuilder(NavigablePath fetchPath, Fetchable fetchable) {
|
||||
public static ImplicitFetchBuilder implicitFetchBuilder(
|
||||
NavigablePath fetchPath,
|
||||
Fetchable fetchable,
|
||||
DomainResultCreationState creationState) {
|
||||
if ( fetchable instanceof BasicValuedModelPart ) {
|
||||
final BasicValuedModelPart basicValuedFetchable = (BasicValuedModelPart) fetchable;
|
||||
return new ImplicitFetchBuilderBasic( fetchPath, basicValuedFetchable );
|
||||
|
@ -251,7 +255,7 @@ public class Builders {
|
|||
|
||||
if ( fetchable instanceof EmbeddableValuedFetchable ) {
|
||||
final EmbeddableValuedFetchable embeddableValuedFetchable = (EmbeddableValuedFetchable) fetchable;
|
||||
return new ImplicitFetchBuilderEmbeddable( fetchPath, embeddableValuedFetchable );
|
||||
return new ImplicitFetchBuilderEmbeddable( fetchPath, embeddableValuedFetchable, creationState );
|
||||
}
|
||||
|
||||
if ( fetchable instanceof EntityValuedFetchable ) {
|
||||
|
|
|
@ -20,7 +20,9 @@ import org.hibernate.internal.util.collections.Stack;
|
|||
import org.hibernate.internal.util.collections.StandardStack;
|
||||
import org.hibernate.metamodel.mapping.AssociationKey;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.internal.NonAggregatedIdentifierMappingImpl;
|
||||
import org.hibernate.query.EntityIdentifierNavigablePath;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
|
@ -39,7 +41,9 @@ import org.hibernate.sql.results.ResultsLogger;
|
|||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
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.embeddable.EmbeddableValuedFetchable;
|
||||
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
@ -113,10 +117,18 @@ public class DomainResultCreationStateImpl
|
|||
return jdbcResultsMetadata;
|
||||
}
|
||||
|
||||
public NavigablePath getCurrentRelativePath() {
|
||||
return relativePathStack.getCurrent();
|
||||
}
|
||||
|
||||
public void pushExplicitFetchMementoResolver(Function<String, FetchBuilder> resolver) {
|
||||
fetchBuilderResolverStack.push( resolver );
|
||||
}
|
||||
|
||||
public Function<String, FetchBuilder> getCurrentExplicitFetchMementoResolver() {
|
||||
return fetchBuilderResolverStack.getCurrent();
|
||||
}
|
||||
|
||||
public Function<String, FetchBuilder> popExplicitFetchMementoResolver() {
|
||||
return fetchBuilderResolverStack.pop();
|
||||
}
|
||||
|
@ -299,75 +311,71 @@ public class DomainResultCreationStateImpl
|
|||
|
||||
final List<Fetch> fetches = CollectionHelper.arrayList( fetchableContainer.getNumberOfFetchables() );
|
||||
|
||||
final Consumer<Fetchable> fetchableConsumer = fetchable -> {
|
||||
final String fetchableName = fetchable.getFetchableName();
|
||||
final NavigablePath fetchPath = fetchParent.getNavigablePath().append( fetchableName );
|
||||
final NavigablePath relativePath = relativePathStack.isEmpty()
|
||||
? new NavigablePath( fetchableName )
|
||||
: relativePathStack.getCurrent().append( fetchableName );
|
||||
|
||||
relativePathStack.push( relativePath );
|
||||
try {
|
||||
final FetchBuilder explicitFetchBuilder = fetchBuilderResolverStack
|
||||
.getCurrent()
|
||||
.apply( relativePath.getFullPath() );
|
||||
final FetchBuilder fetchBuilder = explicitFetchBuilder != null
|
||||
? explicitFetchBuilder
|
||||
: Builders.implicitFetchBuilder( fetchPath, fetchable, this );
|
||||
final Fetch fetch = fetchBuilder.buildFetch(
|
||||
fetchParent,
|
||||
fetchPath,
|
||||
jdbcResultsMetadata,
|
||||
(s, s2) -> {
|
||||
throw new UnsupportedOperationException();
|
||||
},
|
||||
this
|
||||
);
|
||||
fetches.add( fetch );
|
||||
}
|
||||
finally {
|
||||
relativePathStack.pop();
|
||||
}
|
||||
};
|
||||
|
||||
boolean previous = this.processingKeyFetches;
|
||||
this.processingKeyFetches = true;
|
||||
|
||||
if ( fetchableContainer instanceof EntityValuedFetchable ) {
|
||||
final EntityValuedFetchable entityValuedFetchable = (EntityValuedFetchable) fetchableContainer;
|
||||
if ( fetchableContainer instanceof EntityValuedModelPart ) {
|
||||
final EntityValuedModelPart entityValuedFetchable = (EntityValuedModelPart) fetchableContainer;
|
||||
final EntityIdentifierMapping identifierMapping = entityValuedFetchable.getEntityMappingType().getIdentifierMapping();
|
||||
relativePathStack.push(
|
||||
new EntityIdentifierNavigablePath(
|
||||
relativePathStack.getCurrent(),
|
||||
attributeName( identifierMapping )
|
||||
)
|
||||
);
|
||||
final boolean idClass = identifierMapping instanceof NonAggregatedIdentifierMappingImpl;
|
||||
if ( idClass ) {
|
||||
relativePathStack.push(
|
||||
new EntityIdentifierNavigablePath(
|
||||
relativePathStack.getCurrent(),
|
||||
attributeName( identifierMapping )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
entityValuedFetchable.getEntityMappingType().visitKeyFetchables(
|
||||
fetchable -> {
|
||||
// depends whether these fetchables are the identifier mapping or
|
||||
// the identifier sub-attribuates (if composite)
|
||||
final String fetchableName = fetchable.getFetchableName();
|
||||
final NavigablePath fetchPath = fetchParent.getNavigablePath().append( fetchableName );
|
||||
final NavigablePath relativePath = relativePathStack.isEmpty()
|
||||
? new NavigablePath( fetchableName )
|
||||
: relativePathStack.getCurrent().append( fetchableName );
|
||||
},
|
||||
null
|
||||
);
|
||||
if ( identifierMapping instanceof FetchableContainer ) {
|
||||
// essentially means the entity has a composite id - ask the embeddable to visit its fetchables
|
||||
( (FetchableContainer) identifierMapping ).visitFetchables( fetchableConsumer, null );
|
||||
}
|
||||
else {
|
||||
fetchableConsumer.accept( (Fetchable) identifierMapping );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.processingKeyFetches = previous;
|
||||
this.relativePathStack.pop();
|
||||
if ( idClass ) {
|
||||
this.relativePathStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fetchableContainer.visitFetchables(
|
||||
fetchable -> {
|
||||
final String fetchableName = fetchable.getFetchableName();
|
||||
final NavigablePath fetchPath = fetchParent.getNavigablePath().append( fetchableName );
|
||||
final NavigablePath relativePath = relativePathStack.isEmpty()
|
||||
? new NavigablePath( fetchableName )
|
||||
: relativePathStack.getCurrent().append( fetchableName );
|
||||
|
||||
relativePathStack.push( relativePath );
|
||||
try {
|
||||
final FetchBuilder explicitFetchBuilder = fetchBuilderResolverStack
|
||||
.getCurrent()
|
||||
.apply( relativePath.getFullPath() );
|
||||
final FetchBuilder fetchBuilder = explicitFetchBuilder != null
|
||||
? explicitFetchBuilder
|
||||
: Builders.implicitFetchBuilder( fetchPath, fetchable );
|
||||
|
||||
final Fetch fetch = fetchBuilder.buildFetch(
|
||||
fetchParent,
|
||||
fetchPath,
|
||||
jdbcResultsMetadata,
|
||||
(s, s2) -> {
|
||||
throw new UnsupportedOperationException();
|
||||
},
|
||||
this
|
||||
);
|
||||
fetches.add( fetch );
|
||||
}
|
||||
finally {
|
||||
relativePathStack.pop();
|
||||
}
|
||||
},
|
||||
null
|
||||
);
|
||||
fetchableContainer.visitFetchables( fetchableConsumer, null );
|
||||
|
||||
return fetches;
|
||||
}
|
||||
|
|
|
@ -30,19 +30,19 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde
|
|||
private final EntityMappingType entityDescriptor;
|
||||
private final LockMode lockMode;
|
||||
private final ResultBuilderBasicValued discriminatorResultBuilder;
|
||||
private final HashMap<String, FetchBuilder> fetchBuilderMap;
|
||||
private final HashMap<String, FetchBuilder> explicitFetchBuilderMap;
|
||||
|
||||
public CompleteResultBuilderEntityStandard(
|
||||
NavigablePath navigablePath,
|
||||
EntityMappingType entityDescriptor,
|
||||
LockMode lockMode,
|
||||
ResultBuilderBasicValued discriminatorResultBuilder,
|
||||
HashMap<String, FetchBuilder> fetchBuilderMap) {
|
||||
HashMap<String, FetchBuilder> explicitFetchBuilderMap) {
|
||||
this.navigablePath = navigablePath;
|
||||
this.entityDescriptor = entityDescriptor;
|
||||
this.lockMode = lockMode;
|
||||
this.discriminatorResultBuilder = discriminatorResultBuilder;
|
||||
this.fetchBuilderMap = fetchBuilderMap;
|
||||
this.explicitFetchBuilderMap = explicitFetchBuilderMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -62,41 +62,49 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde
|
|||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
final DomainResultCreationStateImpl impl = ResultsHelper.impl( domainResultCreationState );
|
||||
impl.disallowPositionalSelections();
|
||||
|
||||
// we just want it added to the registry
|
||||
impl.getFromClauseAccess().resolveTableGroup(
|
||||
navigablePath,
|
||||
np -> entityDescriptor.createRootTableGroup(
|
||||
navigablePath,
|
||||
null,
|
||||
false,
|
||||
lockMode,
|
||||
() -> predicate -> {},
|
||||
impl,
|
||||
impl.getCreationContext()
|
||||
)
|
||||
);
|
||||
impl.pushExplicitFetchMementoResolver( explicitFetchBuilderMap::get );
|
||||
|
||||
final BasicResult<?> discriminatorResult;
|
||||
if ( discriminatorResultBuilder != null ) {
|
||||
discriminatorResult = discriminatorResultBuilder.buildResult(
|
||||
jdbcResultsMetadata,
|
||||
resultPosition,
|
||||
legacyFetchResolver,
|
||||
try {
|
||||
// we just want it added to the registry
|
||||
impl.getFromClauseAccess().resolveTableGroup(
|
||||
navigablePath,
|
||||
np -> entityDescriptor.createRootTableGroup(
|
||||
navigablePath,
|
||||
null,
|
||||
false,
|
||||
lockMode,
|
||||
() -> predicate -> {},
|
||||
impl,
|
||||
impl.getCreationContext()
|
||||
)
|
||||
);
|
||||
|
||||
final BasicResult<?> discriminatorResult;
|
||||
if ( discriminatorResultBuilder != null ) {
|
||||
discriminatorResult = discriminatorResultBuilder.buildResult(
|
||||
jdbcResultsMetadata,
|
||||
resultPosition,
|
||||
legacyFetchResolver,
|
||||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
else {
|
||||
discriminatorResult = null;
|
||||
}
|
||||
|
||||
return new EntityResultImpl(
|
||||
navigablePath,
|
||||
entityDescriptor,
|
||||
null,
|
||||
lockMode,
|
||||
discriminatorResult,
|
||||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
else {
|
||||
discriminatorResult = null;
|
||||
finally {
|
||||
impl.popExplicitFetchMementoResolver();
|
||||
}
|
||||
|
||||
return new EntityResultImpl(
|
||||
navigablePath,
|
||||
entityDescriptor,
|
||||
null,
|
||||
lockMode,
|
||||
discriminatorResult,
|
||||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.function.BiFunction;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.ConvertibleModelPart;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
|
@ -71,6 +72,14 @@ public class ImplicitFetchBuilderBasic implements ImplicitFetchBuilder {
|
|||
.getTypeConfiguration()
|
||||
);
|
||||
|
||||
final BasicValueConverter valueConverter;
|
||||
if ( fetchable instanceof ConvertibleModelPart ) {
|
||||
valueConverter = ( (ConvertibleModelPart) fetchable ).getValueConverter();
|
||||
}
|
||||
else {
|
||||
valueConverter = null;
|
||||
}
|
||||
|
||||
return new BasicFetch<>(
|
||||
valuesArrayPosition,
|
||||
parent,
|
||||
|
@ -78,7 +87,7 @@ public class ImplicitFetchBuilderBasic implements ImplicitFetchBuilder {
|
|||
fetchable,
|
||||
// todo (6.0) - we don't know
|
||||
true,
|
||||
( (ConvertibleModelPart) fetchable ).getValueConverter(),
|
||||
valueConverter,
|
||||
FetchTiming.IMMEDIATE,
|
||||
domainResultCreationState
|
||||
);
|
||||
|
|
|
@ -6,12 +6,17 @@
|
|||
*/
|
||||
package org.hibernate.query.results.implicit;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.Builders;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||
|
@ -35,12 +40,36 @@ import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnRefere
|
|||
public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder {
|
||||
private final NavigablePath fetchPath;
|
||||
private final EmbeddableValuedFetchable fetchable;
|
||||
private final Map<NavigablePath, FetchBuilder> fetchBuilders;
|
||||
|
||||
public ImplicitFetchBuilderEmbeddable(
|
||||
NavigablePath fetchPath,
|
||||
EmbeddableValuedFetchable fetchable) {
|
||||
EmbeddableValuedFetchable fetchable,
|
||||
DomainResultCreationState creationState) {
|
||||
this.fetchPath = fetchPath;
|
||||
this.fetchable = fetchable;
|
||||
final DomainResultCreationStateImpl creationStateImpl = impl( creationState );
|
||||
final NavigablePath relativePath = creationStateImpl.getCurrentRelativePath();
|
||||
final Function<String, FetchBuilder> fetchBuilderResolver = creationStateImpl.getCurrentExplicitFetchMementoResolver();
|
||||
final Map<NavigablePath, FetchBuilder> fetchBuilders = new LinkedHashMap<>( fetchable.getNumberOfFetchables() );
|
||||
fetchable.visitFetchables(
|
||||
subFetchable -> {
|
||||
final NavigablePath subFetchPath = relativePath.append( subFetchable.getFetchableName() );
|
||||
final FetchBuilder explicitFetchBuilder = fetchBuilderResolver
|
||||
.apply( subFetchPath.getFullPath() );
|
||||
if ( explicitFetchBuilder == null ) {
|
||||
fetchBuilders.put(
|
||||
subFetchPath,
|
||||
Builders.implicitFetchBuilder( fetchPath, subFetchable, creationStateImpl )
|
||||
);
|
||||
}
|
||||
else {
|
||||
fetchBuilders.put( subFetchPath, explicitFetchBuilder );
|
||||
}
|
||||
},
|
||||
null
|
||||
);
|
||||
this.fetchBuilders = fetchBuilders;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,30 +99,7 @@ public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder {
|
|||
}
|
||||
);
|
||||
|
||||
fetchable.forEachSelection(
|
||||
(columnIndex, selection) -> {
|
||||
final TableReference tableReference = tableGroup.getTableReference( selection.getContainingTableExpression() );
|
||||
|
||||
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( selection.getSelectionExpression() );
|
||||
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
|
||||
|
||||
final Expression expression = creationStateImpl.resolveSqlExpression(
|
||||
createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
|
||||
processingState -> new SqlSelectionImpl(
|
||||
valuesArrayPosition,
|
||||
selection.getJdbcMapping()
|
||||
)
|
||||
);
|
||||
|
||||
creationStateImpl.resolveSqlSelection(
|
||||
expression,
|
||||
selection.getJdbcMapping().getJavaTypeDescriptor(),
|
||||
creationStateImpl.getSessionFactory().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return fetchable.generateFetch(
|
||||
final Fetch fetch = fetchable.generateFetch(
|
||||
parent,
|
||||
fetchPath,
|
||||
FetchTiming.IMMEDIATE,
|
||||
|
@ -102,6 +108,18 @@ public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder {
|
|||
null,
|
||||
creationState
|
||||
);
|
||||
final FetchParent fetchParent = (FetchParent) fetch;
|
||||
fetchBuilders.forEach(
|
||||
(subFetchPath, fetchBuilder) -> fetchBuilder.buildFetch(
|
||||
fetchParent,
|
||||
subFetchPath,
|
||||
jdbcResultsMetadata,
|
||||
legacyFetchResolver,
|
||||
creationState
|
||||
)
|
||||
);
|
||||
|
||||
return fetch;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -152,8 +152,8 @@ public class EntityResultTests extends AbstractUsageTest {
|
|||
"select id as id_alias,"
|
||||
+ " type_code as type_code_alias,"
|
||||
+ " root_name as root_name_alias,"
|
||||
+ " subtype1_name as subtype1_name_alias,"
|
||||
+ " subtype2_name as subtype2_name_alias"
|
||||
+ " subtype1_name as sub_type1_name_alias,"
|
||||
+ " subtype2_name as sub_type2_name_alias"
|
||||
+ " from discriminated_entity";
|
||||
|
||||
final List<DiscriminatedRoot> results = session.createNativeQuery( qryString, "root-explicit" ).list();
|
||||
|
|
Loading…
Reference in New Issue