ResultSet mapping

- Basic working support for `@EntityResult`
This commit is contained in:
Steve Ebersole 2020-08-10 13:43:01 -05:00
parent b1e8f64bda
commit 4ad246536f
83 changed files with 1739 additions and 409 deletions

View File

@ -6,8 +6,11 @@
*/
package org.hibernate.boot.query;
import org.hibernate.query.internal.FetchMappingMemento;
import org.hibernate.query.EntityIdentifierNavigablePath;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.named.FetchMemento;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.named.ResultMemento;
/**
* Describes the mapping for a fetch as part of a {@link NamedResultSetMappingDescriptor}
@ -17,5 +20,9 @@ public interface FetchDescriptor {
* Resolve the descriptor into a memento capable of being stored in the
* {@link org.hibernate.query.named.NamedQueryRepository}
*/
FetchMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext);
FetchMemento resolve(ResultSetMappingResolutionContext resolutionContext);
ResultMemento asResultMemento(
NavigablePath path,
ResultSetMappingResolutionContext resolutionContext);
}

View File

@ -13,7 +13,7 @@ import java.util.List;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.internal.ScalarResultMappingMemento;
import org.hibernate.query.internal.ResultMementoBasicStandard;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.type.BasicType;
@ -58,7 +58,7 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
@Override
public NamedResultSetMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
final List<ScalarResultMappingMemento> scalarResultMementos;
final List<ResultMementoBasicStandard> scalarResultMementos;
if ( scalarResultMappings == null || scalarResultMappings.isEmpty() ) {
scalarResultMementos = Collections.emptyList();
}
@ -148,7 +148,7 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
}
@Override
public ScalarResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
public ResultMementoBasicStandard resolve(ResultSetMappingResolutionContext resolutionContext) {
if ( hibernateTypeName != null ) {
final BasicType<?> namedType = resolutionContext.getSessionFactory()
.getTypeConfiguration()
@ -159,12 +159,12 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
throw new IllegalArgumentException( "Could not resolve named type : " + hibernateTypeName );
}
return new ScalarResultMappingMemento( columnName, namedType, resolutionContext );
return new ResultMementoBasicStandard( columnName, namedType, resolutionContext );
}
// todo (6.0) : column name may be optional in HBM - double check
return new ScalarResultMappingMemento( columnName, null, resolutionContext );
return new ResultMementoBasicStandard( columnName, null, resolutionContext );
}
}

View File

@ -6,8 +6,6 @@
*/
package org.hibernate.boot.query;
import org.hibernate.query.internal.FetchMappingMemento;
import org.hibernate.query.internal.ResultMappingMemento;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.named.NamedResultSetMappingMemento;

View File

@ -6,7 +6,7 @@
*/
package org.hibernate.boot.query;
import org.hibernate.query.internal.ResultMappingMemento;
import org.hibernate.query.named.ResultMemento;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
/**
@ -19,5 +19,5 @@ public interface ResultDescriptor {
* Resolve the descriptor into a memento capable of being stored in the
* {@link org.hibernate.query.named.NamedQueryRepository}
*/
ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext);
ResultMemento resolve(ResultSetMappingResolutionContext resolutionContext);
}

View File

@ -17,26 +17,35 @@ import javax.persistence.EntityResult;
import javax.persistence.FieldResult;
import javax.persistence.SqlResultSetMapping;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.BootLogging;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.MutableObject;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.RuntimeMetamodels;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
import org.hibernate.query.EntityIdentifierNavigablePath;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.internal.BasicFetchMemento;
import org.hibernate.query.internal.EntityResultMappingMemento;
import org.hibernate.query.internal.FetchMappingMemento;
import org.hibernate.query.internal.InstantiationResultMappingMemento;
import org.hibernate.query.internal.InstantiationResultMappingMemento.ArgumentMemento;
import org.hibernate.query.internal.FetchMementoBasicStandard;
import org.hibernate.query.internal.ModelPartResultMementoBasicImpl;
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl;
import org.hibernate.query.internal.ResultMappingMemento;
import org.hibernate.query.internal.ResultMementoBasicStandard;
import org.hibernate.query.internal.ResultMementoEntityStandard;
import org.hibernate.query.internal.ResultMementoInstantiationStandard;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.internal.ScalarResultMappingMemento;
import org.hibernate.query.named.FetchMemento;
import org.hibernate.query.named.ModelPartResultMementoBasic;
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.type.descriptor.java.JavaTypeDescriptor;
/**
@ -74,7 +83,7 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
for ( int i = 0; i < entityResults.length; i++ ) {
final EntityResult entityResult = entityResults[i];
resultDescriptors.add(
EntityResultDescriptor.from( entityResult, context )
new EntityResultDescriptor( entityResult, mappingAnnotation, context )
);
}
@ -117,7 +126,7 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
@Override
public NamedResultSetMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
final List<ResultMappingMemento> resultMementos = CollectionHelper.arrayList( resultDescriptors.size() );
final List<ResultMemento> resultMementos = CollectionHelper.arrayList( resultDescriptors.size() );
resultDescriptors.forEach(
resultDescriptor -> resultMementos.add( resultDescriptor.resolve( resolutionContext ) )
@ -142,14 +151,14 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
}
@Override
public ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
public ResultMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
BootLogging.LOGGER.debugf(
"Generating ScalarResultMappingMemento for JPA ColumnResult(%s) for ResultSet mapping `%s`",
columnResult.name(),
mappingName
);
return new ScalarResultMappingMemento( columnResult, resolutionContext );
return new ResultMementoBasicStandard( columnResult, resolutionContext );
}
}
@ -197,7 +206,7 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
}
@Override
public ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
public ResultMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
BootLogging.LOGGER.debugf(
"Generating InstantiationResultMappingMemento for JPA ConstructorResult(%s) for ResultSet mapping `%s`",
targetJavaType.getName(),
@ -215,7 +224,7 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
.getJavaTypeDescriptorRegistry()
.getDescriptor( targetJavaType );
return new InstantiationResultMappingMemento( targetJtd, argumentResultMementos );
return new ResultMementoInstantiationStandard( targetJtd, argumentResultMementos );
}
}
@ -223,17 +232,25 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
* @see javax.persistence.EntityResult
*/
public static class EntityResultDescriptor implements ResultDescriptor {
private final NavigablePath navigablePath;
private String resultSetMappingName;
private final NavigablePath navigablePath;
private final String entityName;
private final String discriminatorColumn;
private final Map<String, AttributeFetchDescriptor> fetchMappings;
public static EntityResultDescriptor from(EntityResult entityResult, MetadataBuildingContext context) {
final String entityName = entityResult.entityClass().getName();
public EntityResultDescriptor(
EntityResult entityResult,
SqlResultSetMapping mappingAnnotation,
MetadataBuildingContext context) {
this.resultSetMappingName = mappingAnnotation.name();
this.entityName = entityResult.entityClass().getName();
this.discriminatorColumn = entityResult.discriminatorColumn();
final Map<String, AttributeFetchDescriptor> fetchMappings = new HashMap<>();
this.navigablePath = new NavigablePath( entityName );
this.fetchMappings = new HashMap<>();
for ( int i = 0; i < entityResult.fields().length; i++ ) {
final FieldResult fieldResult = entityResult.fields()[ i ];
final AttributeFetchDescriptor existing = fetchMappings.get( fieldResult.name() );
@ -243,62 +260,107 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
else {
fetchMappings.put(
fieldResult.name(),
AttributeFetchDescriptor.from( entityName, fieldResult, context )
AttributeFetchDescriptor.from( navigablePath, entityName, fieldResult, context )
);
}
}
return new EntityResultDescriptor(
entityName,
entityResult.discriminatorColumn(),
fetchMappings
);
}
public EntityResultDescriptor(
String entityName,
String discriminatorColumn,
Map<String, AttributeFetchDescriptor> fetchMappings) {
this.navigablePath = new NavigablePath( entityName );
this.entityName = entityName;
this.discriminatorColumn = discriminatorColumn;
this.fetchMappings = fetchMappings;
}
@Override
public ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
public ResultMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels();
final EntityMappingType entityDescriptor = runtimeMetamodels.getEntityMappingType( entityName );
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
final String identifierAttributeName = identifierMapping instanceof SingleAttributeIdentifierMapping
? ( (SingleAttributeIdentifierMapping) identifierMapping ).getAttributeName()
: EntityIdentifierMapping.ROLE_LOCAL_NAME;
final Map<String, FetchMappingMemento> fetchMementos = new HashMap<>();
fetchMappings.forEach(
(attrName, attrMapping) -> fetchMementos.put( attrName, attrMapping.resolve( resolutionContext ) )
final MutableObject<ResultMemento> identifierMementoReference = new MutableObject<>();
final ResultMementoBasic discriminatorMemento = resolveDiscriminatorMemento(
entityDescriptor,
discriminatorColumn,
navigablePath
);
return new EntityResultMappingMemento( entityDescriptor, discriminatorColumn, fetchMementos );
final Map<String, FetchMemento> fetchMementos = new HashMap<>();
fetchMappings.forEach(
(attrName, attrMapping) -> {
if ( EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( attrName )
|| identifierAttributeName.equals( attrName ) ) {
final EntityIdentifierNavigablePath idPath = new EntityIdentifierNavigablePath( navigablePath );
identifierMementoReference.set( attrMapping.asResultMemento( idPath, resolutionContext ) );
}
else {
fetchMementos.put( attrName, attrMapping.resolve( resolutionContext ) );
}
}
);
if ( identifierMementoReference.isNotSet() ) {
throw new IllegalStateException(
String.format(
Locale.ROOT,
"Entity identifier mapping not specified for @EntityResult(%s) for ResultSet mapping `%s`",
entityDescriptor.getEntityName(),
resultSetMappingName
)
);
}
return new ResultMementoEntityStandard(
entityDescriptor,
LockMode.READ,
identifierMementoReference.get(),
discriminatorMemento,
fetchMementos
);
}
private static ModelPartResultMementoBasic resolveDiscriminatorMemento(
EntityMappingType entityMapping,
String discriminatorColumn,
NavigablePath entityPath) {
final EntityDiscriminatorMapping discriminatorMapping = entityMapping.getDiscriminatorMapping();
if ( discriminatorMapping == null ) {
return null;
}
return new ModelPartResultMementoBasicImpl(
entityPath.append( EntityDiscriminatorMapping.ROLE_NAME ),
discriminatorMapping,
discriminatorColumn
);
}
}
private static class AttributeFetchDescriptor implements FetchDescriptor {
private static AttributeFetchDescriptor from(
NavigablePath entityPath,
String entityName,
FieldResult fieldResult,
MetadataBuildingContext context) {
return new AttributeFetchDescriptor(
entityPath.append( fieldResult.name() ),
entityName,
fieldResult.name(),
fieldResult.column()
);
}
private final NavigablePath navigablePath;
private final String entityName;
private final String attributeName;
private final List<String> columnNames;
private AttributeFetchDescriptor(String entityName, String attributeName, String columnName) {
private AttributeFetchDescriptor(
NavigablePath attributePath,
String entityName,
String attributeName,
String columnName) {
this.navigablePath = attributePath;
this.entityName = entityName;
this.attributeName = attributeName;
this.columnNames = new ArrayList<>();
@ -322,7 +384,9 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
}
@Override
public FetchMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
public ResultMemento asResultMemento(
NavigablePath path,
ResultSetMappingResolutionContext resolutionContext) {
final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels();
final EntityMappingType entityMapping = runtimeMetamodels.getEntityMappingType( entityName );
@ -336,7 +400,34 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
assert columnNames.size() == 1;
final BasicValuedModelPart basicPart = (BasicValuedModelPart) subPart;
return new BasicFetchMemento( basicPart, columnNames.get( 0 ) );
return new ModelPartResultMementoBasicImpl( path, basicPart, columnNames.get( 0 ) );
}
throw new NotYetImplementedFor6Exception(
"Only support for basic-valued model-parts have been implemented : " + attributeName + " [" + subPart + "]"
);
}
@Override
public FetchMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels();
final EntityMappingType entityMapping = runtimeMetamodels.getEntityMappingType( entityName );
final ModelPart subPart = entityMapping.findSubPart( attributeName, null );
if ( subPart == null ) {
// throw an exception
}
if ( subPart instanceof BasicValuedModelPart ) {
assert columnNames.size() == 1;
final BasicValuedModelPart basicPart = (BasicValuedModelPart) subPart;
return new FetchMementoBasicStandard(
navigablePath,
basicPart,
columnNames.get( 0 )
);
}
throw new NotYetImplementedFor6Exception(

View File

@ -6,6 +6,13 @@
*/
package org.hibernate.internal.util;
/**
* A more performant version of {@link java.util.concurrent.atomic.AtomicLong} in cases
* where we do not have to worry about concurrency. So usually as a variable referenced in
* anonymous-inner or lambda or ...
*
* @author Andrea Boriero
*/
public class MutableLong {
private long value;

View File

@ -0,0 +1,75 @@
/*
* 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.internal.util;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* Mutable object reference. Mainly useful with anonymous code blocks
* and lambdas.
*
* @author Steve Ebersole
* @author Andrea Boriero
*/
public class MutableObject<T> {
private T reference;
public T get() {
return reference;
}
public boolean isSet() {
return reference != null;
}
public boolean isNotSet() {
return reference == null;
}
public void set(T reference) {
this.reference = reference;
}
public void set(T reference, Consumer<T> existingConsumer) {
if ( this.reference != null ) {
existingConsumer.accept( this.reference );
}
this.reference = reference;
}
public void setIfNot(T reference) {
if ( this.reference == null ) {
this.reference = reference;
}
}
public void setIfNot(T reference, Supplier<RuntimeException> overwriteHandler) {
if ( this.reference == null ) {
this.reference = reference;
}
else {
throw overwriteHandler.get();
}
}
public void setIfNot(Supplier<T> referenceSupplier) {
if ( this.reference == null ) {
this.reference = referenceSupplier.get();
}
}
public void setIfNot(Supplier<T> referenceSupplier, Supplier<RuntimeException> overwriteHandler) {
if ( this.reference == null ) {
this.reference = referenceSupplier.get();
}
else {
throw overwriteHandler.get();
}
}
}

View File

@ -40,7 +40,7 @@ import static org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer.UNFETCH
*
* @author Steve Ebersole
*/
public interface EntityMappingType extends ManagedMappingType, Loadable {
public interface EntityMappingType extends ManagedMappingType, EntityValuedModelPart, Loadable {
/**
* Safety-net.
*

View File

@ -50,23 +50,29 @@ import org.hibernate.type.spi.TypeConfiguration;
* @author Andrea Boriero
*/
public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMapping, FetchOptions {
private final NavigableRole idRole;
private final String attributeName;
private final PropertyAccess propertyAccess;
private final EntityPersister entityPersister;
private final SessionFactoryImplementor sessionFactory;
private final NavigableRole idRole;
private final String rootTable;
private final String pkColumnName;
private final BasicType idType;
private final SessionFactoryImplementor sessionFactory;
public BasicEntityIdentifierMappingImpl(
EntityPersister entityPersister,
String attributeName,
String rootTable,
String pkColumnName,
BasicType idType,
MappingModelCreationProcess creationProcess
) {
assert entityPersister.hasIdentifierProperty();
assert entityPersister.getIdentifierPropertyName() != null;
MappingModelCreationProcess creationProcess) {
assert attributeName != null;
this.attributeName = attributeName;
this.rootTable = rootTable;
this.pkColumnName = pkColumnName;
this.idType = idType;
@ -88,6 +94,11 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
return propertyAccess;
}
@Override
public String getAttributeName() {
return attributeName;
}
@Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
if ( entity instanceof HibernateProxy ) {

View File

@ -17,4 +17,6 @@ public interface SingleAttributeIdentifierMapping extends EntityIdentifierMappin
* Access to the identifier attribute's PropertyAccess
*/
PropertyAccess getPropertyAccess();
String getAttributeName();
}

View File

@ -14,9 +14,7 @@ import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.OneToOne;
import org.hibernate.mapping.ToOne;
import org.hibernate.metamodel.mapping.AssociationKey;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ManagedMappingType;
@ -227,6 +225,8 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
if ( creationState.isAssociationKeyVisited( associationKey ) ) {
NavigablePath parentNavigablePath = fetchablePath.getParent();
assert parentNavigablePath.equals( fetchParent.getNavigablePath() );
ModelPart modelPart = creationState.resolveModelPart( parentNavigablePath );
if ( modelPart instanceof EmbeddedIdentifierMappingImpl ) {
while ( parentNavigablePath instanceof EntityIdentifierNavigablePath ) {
@ -235,6 +235,7 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
}
while ( modelPart instanceof EmbeddableValuedFetchable ) {
parentNavigablePath = parentNavigablePath.getParent();
assert parentNavigablePath != null;
modelPart = creationState.resolveModelPart( parentNavigablePath );
}

View File

@ -6068,6 +6068,7 @@ public abstract class AbstractEntityPersister
return new BasicEntityIdentifierMappingImpl(
this,
bootEntityDescriptor.getIdentifierProperty().getName(),
getTableName(),
rootTableKeyColumnNames[0],
(BasicType) idType,

View File

@ -77,7 +77,7 @@ import org.hibernate.type.VersionType;
* @see org.hibernate.persister.spi.PersisterFactory
* @see org.hibernate.persister.spi.PersisterClassResolver
*/
public interface EntityPersister extends EntityDefinition, EntityValuedModelPart, InFlightEntityMappingType, Loadable, RootTableGroupProducer {
public interface EntityPersister extends EntityDefinition, InFlightEntityMappingType, Loadable, RootTableGroupProducer {
/**
* The property name of the "special" identifier property in HQL

View File

@ -34,6 +34,7 @@ import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.RootGraph;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.persister.entity.EntityPersister;
@ -84,7 +85,7 @@ public class ProcedureCallImpl<R>
private final ProcedureParameterMetadataImpl parameterMetadata;
private final ProcedureParamBindings paramBindings;
private final ResultSetMapping resultSetMapping = new ResultSetMappingImpl();
private final ResultSetMapping resultSetMapping;
private Set<String> synchronizedQuerySpaces;
@ -106,6 +107,8 @@ public class ProcedureCallImpl<R>
this.parameterMetadata = new ProcedureParameterMetadataImpl();
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
this.resultSetMapping = new ResultSetMappingImpl( procedureName );
this.synchronizedQuerySpaces = null;
}
/**
@ -127,6 +130,10 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = new HashSet<>();
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultClasses );
this.resultSetMapping = new ResultSetMappingImpl( mappingId );
Util.resolveResultSetMappingClasses(
resultClasses,
resultSetMapping,
@ -157,6 +164,9 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = new HashSet<>();
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultSetMappingNames );
this.resultSetMapping = new ResultSetMappingImpl( mappingId );
Util.resolveResultSetMappingNames(
resultSetMappingNames,
resultSetMapping,
@ -181,6 +191,8 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
this.resultSetMapping = new ResultSetMappingImpl( memento.getRegistrationName() );
Util.resolveResultSetMappings(
memento.getResultSetMappingNames(),
memento.getResultSetMappingClasses(),
@ -211,6 +223,9 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultTypes );
this.resultSetMapping = new ResultSetMappingImpl( mappingId );
Util.resolveResultSetMappings(
null,
resultTypes,
@ -235,6 +250,9 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultSetMappingNames );
this.resultSetMapping = new ResultSetMappingImpl( mappingId );
Util.resolveResultSetMappings(
resultSetMappingNames,
null,

View File

@ -1,61 +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.Map;
import java.util.function.Consumer;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.ResultBuilder;
/**
* @author Steve Ebersole
*/
public class EntityResultMappingMemento implements ResultMappingMemento, FetchMappingMemento.Parent {
private final NavigablePath navigablePath;
private final EntityMappingType entityDescriptor;
private final String discriminatorColumnAlias;
private final Map<String,FetchMappingMemento> fetchMementoMap;
public EntityResultMappingMemento(
EntityMappingType entityDescriptor,
String discriminatorColumnAlias,
Map<String, FetchMappingMemento> fetchMementoMap) {
this.navigablePath = new NavigablePath( entityDescriptor.getEntityName() );
this.entityDescriptor = entityDescriptor;
this.discriminatorColumnAlias = discriminatorColumnAlias;
this.fetchMementoMap = fetchMementoMap;
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public ManagedMappingType getMappingType() {
return entityDescriptor;
}
@Override
public ResultBuilder resolve(
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context) {
throw new NotYetImplementedFor6Exception( getClass() );
// final Map<String, FetchBuilder> fetchBuilderMap = new HashMap<>();
// fetchMementoMap.forEach(
// (fetchableName, memento) -> fetchBuilderMap.put(
// fetchableName,
// memento.resolve( this, querySpaceConsumer, context )
// )
// );
// return new DynamicResultBuilderEntityStandard( entityDescriptor, null, discriminatorColumnAlias, fetchBuilderMap );
}
}

View File

@ -9,6 +9,10 @@ package org.hibernate.query.internal;
import java.util.function.Consumer;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.named.FetchMementoBasic;
import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.complete.CompleteFetchBuilderBasicPart;
@ -18,20 +22,40 @@ import org.hibernate.query.results.complete.CompleteFetchBuilderBasicPart;
*
* @author Steve Ebersole
*/
public class BasicFetchMemento implements FetchMappingMemento {
public class FetchMementoBasicStandard implements FetchMementoBasic {
private final NavigablePath navigablePath;
private final BasicValuedModelPart fetchedAttribute;
private final String columnAlias;
public BasicFetchMemento(BasicValuedModelPart fetchedAttribute, String columnAlias) {
public FetchMementoBasicStandard(
NavigablePath navigablePath,
BasicValuedModelPart fetchedAttribute,
String columnAlias) {
this.navigablePath = navigablePath;
this.fetchedAttribute = fetchedAttribute;
this.columnAlias = columnAlias;
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public ModelPart getReferencedModelPart() {
return fetchedAttribute;
}
@Override
public MappingType getMappingType() {
return fetchedAttribute.getPartMappingType();
}
@Override
public FetchBuilder resolve(
Parent parent,
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context) {
return new CompleteFetchBuilderBasicPart( fetchedAttribute, columnAlias );
return new CompleteFetchBuilderBasicPart( navigablePath, fetchedAttribute, columnAlias );
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.named.ModelPartResultMementoBasic;
import org.hibernate.query.results.ResultBuilderBasicValued;
import org.hibernate.query.results.complete.CompleteResultBuilderBasicModelPart;
import org.hibernate.query.results.complete.CompleteResultBuilderBasicValuedStandard;
/**
* @author Steve Ebersole
*/
public class ModelPartResultMementoBasicImpl implements ModelPartResultMementoBasic {
private final NavigablePath navigablePath;
private final BasicValuedModelPart modelPart;
private final String columnName;
public ModelPartResultMementoBasicImpl(
NavigablePath navigablePath,
BasicValuedModelPart modelPart,
String columnName) {
this.navigablePath = navigablePath;
this.modelPart = modelPart;
this.columnName = columnName;
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public BasicValuedModelPart getReferencedModelPart() {
return modelPart;
}
@Override
public ResultBuilderBasicValued resolve(
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context) {
return new CompleteResultBuilderBasicModelPart( navigablePath, modelPart, columnName );
}
}

View File

@ -10,6 +10,7 @@ import java.util.List;
import java.util.function.Consumer;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.named.ResultMemento;
import org.hibernate.query.results.ResultSetMapping;
/**
@ -19,13 +20,13 @@ import org.hibernate.query.results.ResultSetMapping;
*/
public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMemento {
private final String name;
private final List<ResultMappingMemento> resultMappingMementos;
private final List<ResultMemento> resultMementos;
public NamedResultSetMappingMementoImpl(
String name,
List<ResultMappingMemento> resultMappingMementos) {
List<ResultMemento> resultMementos) {
this.name = name;
this.resultMappingMementos = resultMappingMementos;
this.resultMementos = resultMementos;
}
@Override
@ -38,7 +39,7 @@ public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMe
ResultSetMapping resultSetMapping,
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context) {
resultMappingMementos.forEach(
resultMementos.forEach(
memento -> resultSetMapping.addResultBuilder( memento.resolve( querySpaceConsumer, context ) )
);
}

View File

@ -10,7 +10,8 @@ import java.util.function.Consumer;
import javax.persistence.ColumnResult;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.named.ResultMementoBasic;
import org.hibernate.query.results.ResultBuilderBasicValued;
import org.hibernate.query.results.complete.CompleteResultBuilderBasicValuedStandard;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -44,7 +45,7 @@ import org.hibernate.type.spi.TypeConfiguration;
*
* @author Steve Ebersole
*/
public class ScalarResultMappingMemento implements ResultMappingMemento {
public class ResultMementoBasicStandard implements ResultMementoBasic {
public final String explicitColumnName;
@ -54,7 +55,7 @@ public class ScalarResultMappingMemento implements ResultMappingMemento {
/**
* Creation of ScalarResultMappingMemento for JPA descriptor
*/
public ScalarResultMappingMemento(
public ResultMementoBasicStandard(
ColumnResult definition,
ResultSetMappingResolutionContext context) {
this.explicitColumnName = definition.name();
@ -73,7 +74,7 @@ public class ScalarResultMappingMemento implements ResultMappingMemento {
explicitType = null;
}
public ScalarResultMappingMemento(
public ResultMementoBasicStandard(
String explicitColumnName,
BasicType<?> explicitType,
ResultSetMappingResolutionContext context) {
@ -85,21 +86,9 @@ public class ScalarResultMappingMemento implements ResultMappingMemento {
}
@Override
public ResultBuilder resolve(
public ResultBuilderBasicValued resolve(
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context) {
return new CompleteResultBuilderBasicValuedStandard( this, context );
}
public String getExplicitColumnName() {
return explicitColumnName;
}
public BasicType<?> getExplicitType() {
return explicitType;
}
public JavaTypeDescriptor<?> getExplicitJavaTypeDescriptor() {
return explicitJavaTypeDescriptor;
return new CompleteResultBuilderBasicValuedStandard( explicitColumnName, explicitType, explicitJavaTypeDescriptor );
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.named.FetchMemento;
import org.hibernate.query.named.ResultMemento;
import org.hibernate.query.named.ResultMementoBasic;
import org.hibernate.query.named.ResultMementoEntity;
import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.ResultBuilderBasicValued;
import org.hibernate.query.results.ResultBuilderEntityValued;
import org.hibernate.query.results.complete.CompleteResultBuilderEntityStandard;
/**
* @author Steve Ebersole
*/
public class ResultMementoEntityStandard implements ResultMementoEntity, FetchMemento.Parent {
private final NavigablePath navigablePath;
private final EntityMappingType entityDescriptor;
private final LockMode lockMode;
private final ResultMemento identifierMemento;
private final ResultMementoBasic discriminatorMemento;
private final Map<String, FetchMemento> fetchMementoMap;
public ResultMementoEntityStandard(
EntityMappingType entityDescriptor,
LockMode lockMode,
ResultMemento identifierMemento,
ResultMementoBasic discriminatorMemento,
Map<String, FetchMemento> fetchMementoMap) {
this.navigablePath = new NavigablePath( entityDescriptor.getEntityName() );
this.entityDescriptor = entityDescriptor;
this.lockMode = lockMode;
this.identifierMemento = identifierMemento;
this.discriminatorMemento = discriminatorMemento;
this.fetchMementoMap = fetchMementoMap;
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public EntityMappingType getReferencedModelPart() {
return entityDescriptor;
}
@Override
public ManagedMappingType getMappingType() {
return entityDescriptor;
}
@Override
public ResultBuilderEntityValued resolve(
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context) {
final ResultBuilder identifierResultBuilder = identifierMemento.resolve(
querySpaceConsumer,
context
);
final ResultBuilderBasicValued discriminatorResultBuilder = discriminatorMemento != null
? discriminatorMemento.resolve( querySpaceConsumer, context )
: null;
final HashMap<String, FetchBuilder> fetchBuilderMap = new HashMap<>();
fetchMementoMap.forEach(
(attrName, fetchMemento) -> fetchBuilderMap.put(
attrName,
fetchMemento.resolve(this, querySpaceConsumer, context )
)
);
return new CompleteResultBuilderEntityStandard(
navigablePath,
entityDescriptor,
lockMode,
identifierResultBuilder,
discriminatorResultBuilder,
fetchBuilderMap
);
}
}

View File

@ -10,6 +10,7 @@ import java.util.List;
import java.util.function.Consumer;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.query.named.ResultMementoInstantiation;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.complete.CompleteResultBuilderInstantiation;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -17,23 +18,12 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public class InstantiationResultMappingMemento implements ResultMappingMemento {
public static class ArgumentMemento {
private final ResultMappingMemento argumentMemento;
public ArgumentMemento(ResultMappingMemento argumentMemento) {
this.argumentMemento = argumentMemento;
}
public ResultBuilder resolve(Consumer<String> querySpaceConsumer, ResultSetMappingResolutionContext context) {
return argumentMemento.resolve( querySpaceConsumer, context );
}
}
public class ResultMementoInstantiationStandard implements ResultMementoInstantiation {
private final JavaTypeDescriptor<?> instantiatedJtd;
private final List<ArgumentMemento> argumentMementos;
public InstantiationResultMappingMemento(
public ResultMementoInstantiationStandard(
JavaTypeDescriptor<?> instantiatedJtd,
List<ArgumentMemento> argumentMementos) {
this.instantiatedJtd = instantiatedJtd;

View File

@ -4,30 +4,34 @@
* 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;
package org.hibernate.query.named;
import java.util.function.Consumer;
import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.query.NavigablePath;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.results.FetchBuilder;
/**
* @author Steve Ebersole
*/
public interface FetchMappingMemento {
interface Parent {
/**
* The path for the parent
*/
NavigablePath getNavigablePath();
public interface FetchMemento extends ModelPartReferenceMemento {
/**
* The parent node for the fetch
*/
interface Parent extends ModelPartReferenceMemento {
/**
* The entity descriptor that is the base for this path/parent
*/
ManagedMappingType getMappingType();
}
/**
* The mapping descriptor for the fetchable
*/
MappingType getMappingType();
/**
* Resolve the fetch-memento into the result-graph-node builder
*/

View File

@ -0,0 +1,24 @@
/*
* 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.named;
import java.util.function.Consumer;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.named.FetchMemento;
import org.hibernate.query.results.FetchBuilder;
/**
* @author Steve Ebersole
*/
public interface FetchMementoBasic extends FetchMemento {
@Override
FetchBuilder resolve(
Parent parent,
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context);
}

View File

@ -0,0 +1,28 @@
/*
* 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.named;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.query.NavigablePath;
/**
* A ResultMappingMementoNode that is a reference to some part of the user's
* domain model
*
* @author Steve Ebersole
*/
public interface ModelPartReferenceMemento extends ResultMappingMementoNode {
/**
* Path to the memento, relative to the result roots
*/
NavigablePath getNavigablePath();
/**
* The referenced domain model part
*/
ModelPart getReferencedModelPart();
}

View File

@ -0,0 +1,13 @@
/*
* 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.named;
/**
* @author Steve Ebersole
*/
public interface ModelPartResultMemento extends ModelPartReferenceMemento, ResultMemento {
}

View File

@ -0,0 +1,17 @@
/*
* 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.named;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
/**
* @author Steve Ebersole
*/
public interface ModelPartResultMementoBasic extends ModelPartResultMemento, ResultMementoBasic {
@Override
BasicValuedModelPart getReferencedModelPart();
}

View File

@ -0,0 +1,13 @@
/*
* 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.named;
/**
* @author Steve Ebersole
*/
public interface ModelPartResultMementoEntity extends ModelPartResultMemento, ResultMementoEntity {
}

View File

@ -0,0 +1,15 @@
/*
* 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.named;
/**
* Any node (result or fetch) in the result graph
*
* @author Steve Ebersole
*/
public interface ResultMappingMementoNode {
}

View File

@ -4,15 +4,20 @@
* 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;
package org.hibernate.query.named;
import java.util.function.Consumer;
import org.hibernate.Incubating;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.results.ResultBuilder;
/**
* @since 6.0
*
* @author Steve Ebersole
*/
public interface ResultMappingMemento {
@Incubating
public interface ResultMemento extends ResultMappingMementoNode {
ResultBuilder resolve(Consumer<String> querySpaceConsumer, ResultSetMappingResolutionContext context);
}

View File

@ -0,0 +1,24 @@
/*
* 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.named;
import java.util.function.Consumer;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.results.ResultBuilderBasicValued;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public interface ResultMementoBasic extends ResultMemento {
@Override
ResultBuilderBasicValued resolve(
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context);
}

View File

@ -0,0 +1,22 @@
/*
* 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.named;
import java.util.function.Consumer;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.results.ResultBuilderEntityValued;
/**
* @author Steve Ebersole
*/
public interface ResultMementoEntity extends ResultMemento {
@Override
ResultBuilderEntityValued resolve(
Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context);
}

View File

@ -0,0 +1,29 @@
/*
* 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.named;
import java.util.function.Consumer;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.results.ResultBuilder;
/**
* @author Steve Ebersole
*/
public interface ResultMementoInstantiation extends ResultMemento {
class ArgumentMemento {
private final ResultMemento argumentMemento;
public ArgumentMemento(ResultMemento argumentMemento) {
this.argumentMemento = argumentMemento;
}
public ResultBuilder resolve(Consumer<String> querySpaceConsumer, ResultSetMappingResolutionContext context) {
return argumentMemento.resolve( querySpaceConsumer, context );
}
}
}

View File

@ -9,60 +9,233 @@ package org.hibernate.query.results;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import org.hibernate.Internal;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.AssociationKey;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.query.results.dynamic.LegacyFetchResolver;
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlAstProcessingState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup;
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.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
/**
* @author Steve Ebersole
*/
public class DomainResultCreationStateImpl implements DomainResultCreationState {
private final List<ResultBuilder> resultBuilders;
private final Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders;
private final SqlAstCreationStateImpl sqlAstCreationState;
@Internal
public class DomainResultCreationStateImpl
implements DomainResultCreationState, SqlAstCreationState, SqlAstProcessingState, SqlExpressionResolver {
private final String stateIdentifier;
private final FromClauseAccessImpl fromClauseAccess;
private final Consumer<SqlSelection> sqlSelectionConsumer;
private final Map<String,SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
private boolean allowPositionalSelections = true;
private final SqlAliasBaseManager sqlAliasBaseManager;
private final LegacyFetchResolverImpl legacyFetchResolver;
private final SessionFactoryImplementor sessionFactory;
public DomainResultCreationStateImpl(
List<ResultBuilder> resultBuilders,
String stateIdentifier,
Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders,
Consumer<SqlSelection> sqlSelectionConsumer,
SessionFactoryImplementor sessionFactory) {
this.resultBuilders = resultBuilders;
this.legacyFetchBuilders = legacyFetchBuilders;
this.stateIdentifier = stateIdentifier;
this.sqlSelectionConsumer = sqlSelectionConsumer;
this.fromClauseAccess = new FromClauseAccessImpl();
this.sqlAstCreationState = new SqlAstCreationStateImpl( fromClauseAccess, sessionFactory );
this.sqlAliasBaseManager = new SqlAliasBaseManager();
this.legacyFetchResolver = new LegacyFetchResolverImpl();
this.legacyFetchResolver = new LegacyFetchResolverImpl( legacyFetchBuilders );
this.sessionFactory = sessionFactory;
}
public LegacyFetchResolver getLegacyFetchResolver() {
return legacyFetchResolver;
}
public SessionFactoryImplementor getSessionFactory() {
return sessionFactory;
}
public int getNumberOfProcessedSelections() {
return sqlSelectionMap.size();
}
public boolean arePositionalSelectionsAllowed() {
return allowPositionalSelections;
}
public void disallowPositionalSelections() {
ResultsLogger.LOGGER.debugf( "Disallowing positional selections : %s", stateIdentifier );
this.allowPositionalSelections = false;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DomainResultCreationState
@Override
public FromClauseAccessImpl getFromClauseAccess() {
return fromClauseAccess;
}
@Override
public SqlAstCreationStateImpl getSqlAstCreationState() {
return sqlAstCreationState;
public DomainResultCreationStateImpl getSqlAstCreationState() {
return this;
}
@FunctionalInterface
public interface LegacyFetchResolver {
DynamicFetchBuilderLegacy resolve(String ownerTableAlias, String fetchedPartPath);
@Override
public SqlAliasBaseManager getSqlAliasBaseManager() {
return sqlAliasBaseManager;
}
@Override
public boolean forceIdentifierSelection() {
return false;
}
@Override
public void registerVisitedAssociationKey(AssociationKey associationKey) {
}
@Override
public boolean isAssociationKeyVisited(AssociationKey associationKey) {
return false;
}
@Override
public ModelPart resolveModelPart(NavigablePath navigablePath) {
final TableGroup tableGroup = fromClauseAccess.findTableGroup( navigablePath );
if ( tableGroup != null ) {
return tableGroup.getModelPart();
}
if ( navigablePath.getParent() != null ) {
final TableGroup parentTableGroup = fromClauseAccess.findTableGroup( navigablePath.getParent() );
if ( parentTableGroup != null ) {
return parentTableGroup.getModelPart().findSubPart( navigablePath.getLocalName(), null );
}
}
return null;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqlAstCreationState
@Override
public DomainResultCreationStateImpl getSqlExpressionResolver() {
return getCurrentProcessingState();
}
@Override
public LockMode determineLockMode(String identificationVariable) {
return LockMode.READ;
}
@Override
public DomainResultCreationStateImpl getCurrentProcessingState() {
return this;
}
public SqlAstCreationContext getCreationContext() {
return getSessionFactory();
}
@Override
public SqlAliasBaseGenerator getSqlAliasBaseGenerator() {
return sqlAliasBaseManager;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqlAstProcessingState
@Override
public SqlAstProcessingState getParentState() {
return null;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqlExpressionResolver
@Override
public Expression resolveSqlExpression(
String key,
Function<SqlAstProcessingState, Expression> creator) {
final SqlSelectionImpl existing = sqlSelectionMap.get( key );
if ( existing != null ) {
return existing;
}
final Expression created = creator.apply( this );
if ( created instanceof SqlSelectionImpl ) {
sqlSelectionMap.put( key, (SqlSelectionImpl) created );
sqlSelectionConsumer.accept( (SqlSelectionImpl) created );
}
else if ( created instanceof ColumnReference ) {
final ColumnReference columnReference = (ColumnReference) created;
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl(
sqlSelectionMap.size() + 1,
columnReference.getJdbcMapping()
);
sqlSelectionMap.put( key, sqlSelection );
sqlSelectionConsumer.accept( sqlSelection );
}
return created;
}
@Override
public SqlSelection resolveSqlSelection(
Expression expression,
JavaTypeDescriptor javaTypeDescriptor,
TypeConfiguration typeConfiguration) {
assert expression instanceof SqlSelectionImpl;
return (SqlSelection) expression;
}
private static class LegacyFetchResolverImpl implements LegacyFetchResolver {
private final Map<String,Map<String, DynamicFetchBuilderLegacy>> legacyFetchResolvers;
private final Map<String,Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders;
public LegacyFetchResolverImpl() {
this.legacyFetchResolvers = new HashMap<>();
public LegacyFetchResolverImpl(Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders) {
this.legacyFetchBuilders = legacyFetchBuilders;
}
@Override
public DynamicFetchBuilderLegacy resolve(String ownerTableAlias, String fetchedPartPath) {
final Map<String, DynamicFetchBuilderLegacy> fetchBuilders = legacyFetchResolvers.get( ownerTableAlias );
if ( legacyFetchBuilders == null ) {
return null;
}
final Map<String, DynamicFetchBuilderLegacy> fetchBuilders = legacyFetchBuilders.get( ownerTableAlias );
if ( fetchBuilders == null ) {
return null;
}
@ -71,10 +244,6 @@ public class DomainResultCreationStateImpl implements DomainResultCreationState
}
}
public LegacyFetchResolver getLegacyFetchResolver() {
return legacyFetchResolver;
}
@Override
public List<Fetch> visitFetches(FetchParent fetchParent) {
throw new UnsupportedOperationException();

View File

@ -7,12 +7,10 @@
package org.hibernate.query.results;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.Incubating;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
@ -28,11 +26,9 @@ import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
*/
@Incubating
public interface FetchBuilder {
Fetch buildFetch(
FetchParent parent,
NavigablePath fetchPath, JdbcValuesMetadata jdbcResultsMetadata,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState);
}

View File

@ -0,0 +1,27 @@
/*
* 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.results;
import org.hibernate.HibernateException;
/**
* Indicates that a column defined as part of a SQL ResultSet mapping was not part
* of the query's ResultSet
*
* @see ResultSetMapping
*
* @author Steve Ebersole
*/
public class MissingSqlSelectionException extends HibernateException {
public MissingSqlSelectionException(String message) {
super( message );
}
public MissingSqlSelectionException(String message, Throwable cause) {
super( message, cause );
}
}

View File

@ -0,0 +1,18 @@
/*
* 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.results;
import org.hibernate.HibernateException;
/**
* @author Steve Ebersole
*/
public class PositionalSelectionsNotAllowedException extends HibernateException {
public PositionalSelectionsNotAllowedException(String message) {
super( message );
}
}

View File

@ -7,11 +7,9 @@
package org.hibernate.query.results;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.Incubating;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -28,6 +26,5 @@ public interface ResultBuilder {
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState);
}

View File

@ -7,10 +7,8 @@
package org.hibernate.query.results;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -26,6 +24,5 @@ public interface ResultBuilderBasicValued extends ResultBuilder {
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState);
}

View File

@ -7,10 +7,8 @@
package org.hibernate.query.results;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -26,6 +24,5 @@ public interface ResultBuilderEntityValued extends ResultBuilder {
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState);
}

View File

@ -36,9 +36,15 @@ import org.hibernate.type.spi.TypeConfiguration;
@Incubating
@Internal
public class ResultSetMappingImpl implements ResultSetMapping {
private final String mappingIdentifier;
private List<ResultBuilder> resultBuilders;
private Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders;
public ResultSetMappingImpl(String mappingIdentifier) {
this.mappingIdentifier = mappingIdentifier;
}
@Override
public int getNumberOfResultBuilders() {
return resultBuilders == null ? 0 : resultBuilders.size();
@ -108,8 +114,9 @@ public class ResultSetMappingImpl implements ResultSetMapping {
final List<DomainResult<?>> domainResults = new ArrayList<>( numberOfResults );
final DomainResultCreationStateImpl creationState = new DomainResultCreationStateImpl(
resultBuilders,
mappingIdentifier,
legacyFetchBuilders,
sqlSelections::add,
sessionFactory
);
@ -131,22 +138,15 @@ public class ResultSetMappingImpl implements ResultSetMapping {
domainResult = resultBuilder.buildResult(
jdbcResultsMetadata,
domainResults.size(),
(entityName, fetchableName) -> {
if ( legacyFetchBuilders == null ) {
return null;
}
final Map<String, DynamicFetchBuilderLegacy> fetchBuilderMap = legacyFetchBuilders.get( entityName );
if ( fetchBuilderMap == null ) {
return null;
}
return fetchBuilderMap.get( fetchableName );
},
sqlSelections::add,
creationState.getLegacyFetchResolver()::resolve,
creationState
);
}
if ( domainResult.containsAnyNonScalarResults() ) {
creationState.disallowPositionalSelections();
}
domainResults.add( domainResult );
}

View File

@ -24,18 +24,6 @@ public class ResultsHelper {
return unwrap( creationState );
}
public static FromClauseAccessImpl extractFromClauseAccess(DomainResultCreationState creationState) {
return unwrap( creationState ).getFromClauseAccess();
}
public static SqlAstCreationStateImpl extractSqlAstCreationState(DomainResultCreationState creationState) {
return unwrap( creationState ).getSqlAstCreationState();
}
public static SqlAstProcessingStateImpl extractSqlAstProcessingState(DomainResultCreationState creationState) {
return unwrap( creationState ).getSqlAstCreationState().getCurrentProcessingState();
}
private static DomainResultCreationStateImpl unwrap(DomainResultCreationState creationState) {
if ( creationState instanceof DomainResultCreationStateImpl ) {
return ( (DomainResultCreationStateImpl) creationState );

View File

@ -6,44 +6,83 @@
*/
package org.hibernate.query.results;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import org.hibernate.Internal;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlAstProcessingState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
/**
* SqlAstCreationState implementation for result-set mapping handling
*
* @author Steve Ebersole
*/
public class SqlAstCreationStateImpl implements SqlAstCreationState {
private final SessionFactoryImplementor sessionFactory;
@Internal
public class SqlAstCreationStateImpl implements SqlAstCreationState, SqlAstProcessingState, SqlExpressionResolver {
private final FromClauseAccessImpl fromClauseAccess;
private final SqlAstProcessingStateImpl processingState;
private final SqlAliasBaseManager sqlAliasBaseManager;
private final Consumer<SqlSelection> sqlSelectionConsumer;
private final Map<String,SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
private final SessionFactoryImplementor sessionFactory;
public SqlAstCreationStateImpl(
FromClauseAccessImpl fromClauseAccess,
SqlAliasBaseManager sqlAliasBaseManager,
Consumer<SqlSelection> sqlSelectionConsumer,
SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory;
this.fromClauseAccess = fromClauseAccess;
this.processingState = new SqlAstProcessingStateImpl( this, fromClauseAccess );
this.sqlAliasBaseManager = sqlAliasBaseManager;
this.sqlSelectionConsumer = sqlSelectionConsumer;
this.sessionFactory = sessionFactory;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqlAstProcessingState
@Override
public SqlAstProcessingState getParentState() {
return null;
}
@Override
public SqlAstCreationState getSqlAstCreationState() {
return this;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqlAstCreationState
@Override
public SqlAstCreationContext getCreationContext() {
return sessionFactory;
}
@Override
public SqlAstProcessingStateImpl getCurrentProcessingState() {
return processingState;
public SqlAstCreationStateImpl getCurrentProcessingState() {
return this;
}
@Override
public SqlAstProcessingStateImpl getSqlExpressionResolver() {
return processingState;
public SqlAstCreationStateImpl getSqlExpressionResolver() {
return this;
}
@Override
@ -53,13 +92,31 @@ public class SqlAstCreationStateImpl implements SqlAstCreationState {
@Override
public SqlAliasBaseGenerator getSqlAliasBaseGenerator() {
return stem -> {
throw new UnsupportedOperationException();
};
return sqlAliasBaseManager;
}
@Override
public LockMode determineLockMode(String identificationVariable) {
return LockMode.READ;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqlExpressionResolver
@Override
public Expression resolveSqlExpression(
String key,
Function<SqlAstProcessingState, Expression> creator) {
return null;
}
@Override
public SqlSelection resolveSqlSelection(
Expression expression,
JavaTypeDescriptor javaTypeDescriptor,
TypeConfiguration typeConfiguration) {
return null;
}
}

View File

@ -8,8 +8,10 @@ package org.hibernate.query.results;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import org.hibernate.Internal;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlAstProcessingState;
@ -23,17 +25,22 @@ import org.hibernate.type.spi.TypeConfiguration;
/**
* @author Steve Ebersole
*/
@Internal
public class SqlAstProcessingStateImpl implements SqlAstProcessingState, SqlExpressionResolver {
private final SqlAstCreationState sqlAstCreationState;
private final FromClauseAccessImpl fromClauseAccess;
private final Map<String,SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
private final Consumer<SqlSelection> sqlSelectionConsumer;
private final SqlAstCreationState sqlAstCreationState;
public SqlAstProcessingStateImpl(
SqlAstCreationState sqlAstCreationState,
FromClauseAccessImpl fromClauseAccess) {
this.sqlAstCreationState = sqlAstCreationState;
FromClauseAccessImpl fromClauseAccess,
Consumer<SqlSelection> sqlSelectionConsumer,
SqlAstCreationState sqlAstCreationState) {
this.fromClauseAccess = fromClauseAccess;
this.sqlSelectionConsumer = sqlSelectionConsumer;
this.sqlAstCreationState = sqlAstCreationState;
}
@Override
@ -69,6 +76,7 @@ public class SqlAstProcessingStateImpl implements SqlAstProcessingState, SqlExpr
if ( created instanceof SqlSelectionImpl ) {
sqlSelectionMap.put( key, (SqlSelectionImpl) created );
sqlSelectionConsumer.accept( (SqlSelectionImpl) created );
}
else if ( created instanceof ColumnReference ) {
final ColumnReference columnReference = (ColumnReference) created;
@ -77,7 +85,9 @@ public class SqlAstProcessingStateImpl implements SqlAstProcessingState, SqlExpr
sqlSelectionMap.size() + 1,
columnReference.getJdbcMapping()
);
sqlSelectionMap.put( key, sqlSelection );
sqlSelectionConsumer.accept( sqlSelection );
}
return created;

View File

@ -7,19 +7,16 @@
package org.hibernate.query.results.complete;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FromClauseAccessImpl;
import org.hibernate.query.results.SqlAstCreationStateImpl;
import org.hibernate.query.results.SqlAstProcessingStateImpl;
import org.hibernate.query.results.MissingSqlSelectionException;
import org.hibernate.query.results.PositionalSelectionsNotAllowedException;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState;
@ -34,13 +31,23 @@ import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnRefere
/**
* @author Steve Ebersole
*/
public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder {
public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder, ModelPartReferenceBasic {
private final NavigablePath navigablePath;
private final BasicValuedModelPart referencedModelPart;
private final String columnName;
private final String selectionAlias;
public CompleteFetchBuilderBasicPart(BasicValuedModelPart referencedModelPart, String columnName) {
public CompleteFetchBuilderBasicPart(
NavigablePath navigablePath,
BasicValuedModelPart referencedModelPart,
String selectionAlias) {
this.navigablePath = navigablePath;
this.referencedModelPart = referencedModelPart;
this.columnName = columnName;
this.selectionAlias = selectionAlias;
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
@ -54,49 +61,48 @@ public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder {
NavigablePath fetchPath,
JdbcValuesMetadata jdbcResultsMetadata,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
final DomainResultCreationStateImpl domainResultCreationStateImpl = impl( domainResultCreationState );
final SqlAstCreationStateImpl sqlAstCreationState = domainResultCreationStateImpl.getSqlAstCreationState();
final FromClauseAccessImpl fromClauseAccess = domainResultCreationStateImpl.getFromClauseAccess();
final SqlAstProcessingStateImpl sqlAstProcessingState = sqlAstCreationState.getCurrentProcessingState();
final DomainResultCreationStateImpl creationState = impl( domainResultCreationState );
final String mappedTable = referencedModelPart.getContainingTableExpression();
final String mappedColumn = referencedModelPart.getMappedColumnExpression();
final TableGroup tableGroup = fromClauseAccess.getTableGroup( parent.getNavigablePath() );
final TableGroup tableGroup = creationState.getFromClauseAccess().getTableGroup( parent.getNavigablePath() );
final TableReference tableReference = tableGroup.getTableReference( mappedTable );
final String selectedAlias;
final int jdbcPosition;
if ( columnName == null ) {
jdbcPosition = sqlAstProcessingState.getNumberOfProcessedSelections();
selectedAlias = jdbcResultsMetadata.resolveColumnName( jdbcPosition );
if ( selectionAlias != null ) {
try {
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( selectionAlias );
}
catch (Exception e) {
throw new MissingSqlSelectionException(
"ResultSet mapping specified selected-alias `" + selectionAlias
+ "` which was not part of the ResultSet",
e
);
}
selectedAlias = selectionAlias;
}
else {
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnName );
selectedAlias = columnName;
if ( ! creationState.arePositionalSelectionsAllowed() ) {
throw new PositionalSelectionsNotAllowedException(
"Positional SQL selection resolution not allowed"
);
}
jdbcPosition = creationState.getNumberOfProcessedSelections();
selectedAlias = jdbcResultsMetadata.resolveColumnName( jdbcPosition );
}
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
// we just care about the registration here. The ModelPart will find it later
sqlAstProcessingState.resolveSqlExpression(
creationState.resolveSqlExpression(
createColumnReferenceKey( tableReference, mappedColumn ),
processingState -> new SqlSelectionImpl( valuesArrayPosition, referencedModelPart )
);
// final Expression expression = sqlAstProcessingState.resolveSqlExpression(
// createColumnReferenceKey( tableReference, mappedColumn ),
// processingState -> new SqlSelectionImpl( valuesArrayPosition, referencedModelPart )
// );
//
// final SqlSelection sqlSelection = sqlAstProcessingState.resolveSqlSelection(
// expression,
// referencedModelPart.getJavaTypeDescriptor(),
// sqlAstCreationState.getCreationContext().getSessionFactory().getTypeConfiguration()
// );
return referencedModelPart.generateFetch(
parent,

View File

@ -0,0 +1,87 @@
/*
* 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.results.complete;
import java.util.function.BiFunction;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import static org.hibernate.query.results.ResultsHelper.impl;
import static org.hibernate.query.results.ResultsHelper.jdbcPositionToValuesArrayPosition;
/**
* CompleteResultBuilder for basic-valued ModelParts
*
* @author Steve Ebersole
*/
public class CompleteResultBuilderBasicModelPart
implements CompleteResultBuilderBasicValued, ModelPartReferenceBasic {
private final NavigablePath navigablePath;
private final BasicValuedModelPart modelPart;
private final String columnAlias;
public CompleteResultBuilderBasicModelPart(
NavigablePath navigablePath,
BasicValuedModelPart modelPart,
String columnAlias) {
this.navigablePath = navigablePath;
this.modelPart = modelPart;
this.columnAlias = columnAlias;
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public BasicValuedModelPart getReferencedPart() {
return modelPart;
}
@Override
public BasicResult<?> buildResult(
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
DomainResultCreationState domainResultCreationState) {
final DomainResultCreationStateImpl creationStateImpl = impl( domainResultCreationState );
final TableGroup tableGroup = creationStateImpl.getFromClauseAccess().getTableGroup( navigablePath.getParent() );
final TableReference tableReference = tableGroup.getTableReference( modelPart.getContainingTableExpression() );
final String mappedColumn = modelPart.getMappedColumnExpression();
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
creationStateImpl.resolveSqlSelection(
creationStateImpl.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( tableReference, mappedColumn ),
processingState -> new SqlSelectionImpl( valuesArrayPosition, modelPart )
),
modelPart.getJavaTypeDescriptor(),
creationStateImpl.getSessionFactory().getTypeConfiguration()
);
//noinspection unchecked
return new BasicResult(
valuesArrayPosition,
columnAlias,
modelPart.getJavaTypeDescriptor()
);
}
}

View File

@ -7,24 +7,22 @@
package org.hibernate.query.results.complete;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.internal.ScalarResultMappingMemento;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.query.results.ResultsHelper.impl;
/**
* ResultBuilder for scalar results defined via:<ul>
* <li>JPA {@link javax.persistence.ColumnResult}</li>
@ -37,15 +35,16 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
private final String explicitColumnName;
private final BasicType<?> explicitType;
private final BasicValuedMapping explicitType;
private final JavaTypeDescriptor<?> explicitJavaTypeDescriptor;
public CompleteResultBuilderBasicValuedStandard(
ScalarResultMappingMemento memento,
ResultSetMappingResolutionContext context) {
this.explicitColumnName = memento.getExplicitColumnName();
this.explicitType = memento.getExplicitType();
this.explicitJavaTypeDescriptor = memento.getExplicitJavaTypeDescriptor();
String explicitColumnName,
BasicValuedMapping explicitType,
JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
this.explicitColumnName = explicitColumnName;
this.explicitType = explicitType;
this.explicitJavaTypeDescriptor = explicitJavaTypeDescriptor;
}
@Override
@ -53,11 +52,9 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
final SessionFactoryImplementor sessionFactory = domainResultCreationState.getSqlAstCreationState()
.getCreationContext()
.getSessionFactory();
final DomainResultCreationStateImpl creationStateImpl = impl( domainResultCreationState );
final SessionFactoryImplementor sessionFactory = creationStateImpl.getSessionFactory();
final int jdbcPosition;
final String columnName;
@ -73,7 +70,7 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
final BasicType<?> basicType;
final BasicValuedMapping basicType;
if ( explicitType != null ) {
basicType = explicitType;
@ -94,10 +91,16 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
basicType = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
}
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
sqlSelectionConsumer.accept( sqlSelection );
creationStateImpl.resolveSqlSelection(
creationStateImpl.resolveSqlExpression(
columnName,
processingState -> new SqlSelectionImpl( valuesArrayPosition, basicType )
),
explicitJavaTypeDescriptor,
sessionFactory.getTypeConfiguration()
);
return new BasicResult<>( valuesArrayPosition, columnName, basicType.getJavaTypeDescriptor() );
return new BasicResult<>( valuesArrayPosition, columnName, basicType.getMappedTypeDescriptor().getMappedJavaTypeDescriptor() );
}
}

View File

@ -0,0 +1,135 @@
/*
* 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.results.complete;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.BiFunction;
import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.ResultBuilderBasicValued;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
/**
* @author Steve Ebersole
*/
public class CompleteResultBuilderEntityStandard implements CompleteResultBuilderEntityValued {
private final NavigablePath navigablePath;
private final EntityMappingType entityDescriptor;
private final LockMode lockMode;
private final ResultBuilder identifierResultBuilder;
private final ResultBuilderBasicValued discriminatorResultBuilder;
private final HashMap<String, FetchBuilder> fetchBuilderMap;
public CompleteResultBuilderEntityStandard(
NavigablePath navigablePath,
EntityMappingType entityDescriptor,
LockMode lockMode,
ResultBuilder identifierResultBuilder,
ResultBuilderBasicValued discriminatorResultBuilder,
HashMap<String, FetchBuilder> fetchBuilderMap) {
this.navigablePath = navigablePath;
this.entityDescriptor = entityDescriptor;
this.lockMode = lockMode;
this.identifierResultBuilder = identifierResultBuilder;
this.discriminatorResultBuilder = discriminatorResultBuilder;
this.fetchBuilderMap = fetchBuilderMap;
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public EntityMappingType getReferencedPart() {
return entityDescriptor;
}
@Override
public EntityResult buildResult(
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
DomainResultCreationState domainResultCreationState) {
final DomainResultCreationStateImpl impl = ResultsHelper.impl( domainResultCreationState );
// we just want it added to the registry
impl.getFromClauseAccess().resolveTableGroup(
navigablePath,
np -> entityDescriptor.createRootTableGroup(
navigablePath,
null,
false,
lockMode,
impl.getSqlAliasBaseManager(),
impl.getSqlAstCreationState().getSqlExpressionResolver(),
() -> predicate -> {},
impl.getSqlAstCreationState().getCreationContext()
)
);
final DomainResult<?> identifierResult = identifierResultBuilder.buildResult(
jdbcResultsMetadata,
resultPosition,
legacyFetchResolver,
domainResultCreationState
);
final BasicResult<?> discriminatorResult;
if ( discriminatorResultBuilder != null ) {
discriminatorResult = discriminatorResultBuilder.buildResult(
jdbcResultsMetadata,
resultPosition,
legacyFetchResolver,
domainResultCreationState
);
}
else {
discriminatorResult = null;
}
return new EntityResultImpl(
navigablePath,
entityDescriptor,
null,
lockMode,
identifierResult,
discriminatorResult,
fetchParent -> {
final List<Fetch> fetches = new ArrayList<>( fetchBuilderMap.size() );
fetchBuilderMap.forEach(
(fetchableName, fetchBuilder) -> fetches.add(
fetchBuilder.buildFetch(
fetchParent,
navigablePath.append( fetchableName ),
jdbcResultsMetadata,
legacyFetchResolver,
domainResultCreationState
)
)
);
return fetches;
}
);
}
}

View File

@ -13,7 +13,7 @@ import org.hibernate.query.results.ResultBuilderEntityValued;
* @author Steve Ebersole
*/
public interface CompleteResultBuilderEntityValued
extends CompleteResultBuilder, ModelPartReference, ResultBuilderEntityValued {
extends CompleteResultBuilder, ModelPartReferenceEntity, ResultBuilderEntityValued {
@Override
EntityMappingType getReferencedPart();
}

View File

@ -9,13 +9,11 @@ package org.hibernate.query.results.complete;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.query.DynamicInstantiationNature;
import org.hibernate.query.results.ResultBuilderInstantiationValued;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.instantiation.internal.ArgumentDomainResult;
@ -46,19 +44,17 @@ public class CompleteResultBuilderInstantiation
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
final List<ArgumentDomainResult<?>> argumentDomainResults = new ArrayList<>( argumentResultBuilders.size() );
for ( int i = 0; i < argumentResultBuilders.size(); i++ ) {
final ResultBuilder argumentResultBuilder = argumentResultBuilders.get( i );
final ArgumentDomainResult<Object> argumentDomainResult = new ArgumentDomainResult<>(
@SuppressWarnings({"unchecked", "rawtypes"}) final ArgumentDomainResult<?> argumentDomainResult = new ArgumentDomainResult(
argumentResultBuilder.buildResult(
jdbcResultsMetadata,
i,
legacyFetchResolver,
sqlSelectionConsumer,
domainResultCreationState
)
);
@ -66,7 +62,7 @@ public class CompleteResultBuilderInstantiation
argumentDomainResults.add( argumentDomainResult );
}
return new DynamicInstantiationResultImpl(
return new DynamicInstantiationResultImpl<>(
null,
DynamicInstantiationNature.CLASS,
javaTypeDescriptor,

View File

@ -0,0 +1,114 @@
/*
* 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.results.complete;
import java.util.List;
import java.util.function.Function;
import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultAssembler;
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.basic.BasicResult;
import org.hibernate.sql.results.graph.entity.EntityInitializer;
import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.graph.entity.internal.EntityAssembler;
import org.hibernate.sql.results.graph.entity.internal.EntityResultInitializer;
/**
* @author Steve Ebersole
*/
public class EntityResultImpl implements EntityResult {
private final NavigablePath navigablePath;
private final EntityValuedModelPart entityValuedModelPart;
private final DomainResult identifierResult;
private final BasicResult discriminatorResult;
private final List<Fetch> fetches;
private final String resultAlias;
private final LockMode lockMode;
public EntityResultImpl(
NavigablePath navigablePath,
EntityValuedModelPart entityValuedModelPart,
String resultAlias,
LockMode lockMode,
DomainResult identifierResult,
BasicResult discriminatorResult,
Function<FetchParent,List<Fetch>> fetchesProducer) {
this.navigablePath = navigablePath;
this.entityValuedModelPart = entityValuedModelPart;
this.resultAlias = resultAlias;
this.lockMode = lockMode;
this.identifierResult = identifierResult;
this.discriminatorResult = discriminatorResult;
this.fetches = fetchesProducer.apply( this );
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public EntityValuedModelPart getReferencedMappingType() {
return entityValuedModelPart;
}
@Override
public EntityValuedModelPart getEntityValuedModelPart() {
return entityValuedModelPart;
}
@Override
public String getResultVariable() {
return resultAlias;
}
@Override
public List<Fetch> getFetches() {
return fetches;
}
@Override
public Fetch findFetch(Fetchable fetchable) {
for ( int i = 0; i < fetches.size(); i++ ) {
if ( fetches.get( i ).getFetchedMapping() == fetchable ) {
return fetches.get( i );
}
}
return null;
}
@Override
public DomainResultAssembler createResultAssembler(AssemblerCreationState creationState) {
final EntityInitializer initializer = (EntityInitializer) creationState.resolveInitializer(
getNavigablePath(),
getReferencedModePart(),
() -> new EntityResultInitializer(
this,
getNavigablePath(),
lockMode,
identifierResult,
discriminatorResult,
null,
null,
creationState
)
);
return new EntityAssembler( getResultJavaTypeDescriptor(), initializer );
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.query.results.complete;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.ResultBuilder;
@ -17,10 +18,10 @@ import org.hibernate.query.results.ResultBuilder;
* @author Steve Ebersole
*/
public interface ModelPartReference {
NavigablePath getNavigablePath();
/**
* The part of the domain model that is referenced
*/
ModelPart getReferencedPart();
}

View File

@ -0,0 +1,17 @@
/*
* 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.results.complete;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
/**
* @author Steve Ebersole
*/
public interface ModelPartReferenceBasic extends ModelPartReference {
@Override
BasicValuedModelPart getReferencedPart();
}

View File

@ -0,0 +1,17 @@
/*
* 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.results.complete;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
/**
* @author Steve Ebersole
*/
public interface ModelPartReferenceCollection extends ModelPartReference {
@Override
PluralAttributeMapping getReferencedPart();
}

View File

@ -0,0 +1,17 @@
/*
* 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.results.complete;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
/**
* @author Steve Ebersole
*/
public interface ModelPartReferenceEmbeddable extends ModelPartReference {
@Override
EmbeddableValuedModelPart getReferencedPart();
}

View File

@ -0,0 +1,17 @@
/*
* 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.results.complete;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
/**
* @author Steve Ebersole
*/
public interface ModelPartReferenceEntity extends ModelPartReference {
@Override
EntityValuedModelPart getReferencedPart();
}

View File

@ -8,15 +8,13 @@ package org.hibernate.query.results.dynamic;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.FromClauseAccessImpl;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
@ -64,11 +62,10 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
NavigablePath fetchPath,
JdbcValuesMetadata jdbcResultsMetadata,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
final FromClauseAccessImpl fromClauseAccess = ResultsHelper.extractFromClauseAccess( domainResultCreationState );
final DomainResultCreationStateImpl creationState = ResultsHelper.impl( domainResultCreationState );
final TableGroup ownerTableGroup = fromClauseAccess.findByAlias( ownerTableAlias );
final TableGroup ownerTableGroup = creationState.getFromClauseAccess().findByAlias( ownerTableAlias );
// todo (6.0) : create the TableGroupJoin for the fetch and then build the fetch

View File

@ -9,14 +9,12 @@ package org.hibernate.query.results.dynamic;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.FromClauseAccessImpl;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
@ -47,11 +45,10 @@ public class DynamicFetchBuilderStandard
NavigablePath fetchPath,
JdbcValuesMetadata jdbcResultsMetadata,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
final FromClauseAccessImpl fromClauseAccess = ResultsHelper.extractFromClauseAccess( domainResultCreationState );
final DomainResultCreationStateImpl creationStateImpl = ResultsHelper.impl( domainResultCreationState );
final TableGroup ownerTableGroup = fromClauseAccess.getTableGroup( parent.getNavigablePath() );
final TableGroup ownerTableGroup = creationStateImpl.getFromClauseAccess().getTableGroup( parent.getNavigablePath() );
// todo (6.0) : create the TableGroupJoin for the fetch and then build the fetch

View File

@ -8,12 +8,12 @@ package org.hibernate.query.results.dynamic;
import java.util.Locale;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
@ -59,15 +59,21 @@ public class DynamicResultBuilderAttribute implements DynamicResultBuilder {
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
final int resultSetPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = resultSetPosition - 1;
// todo (6.0) : TableGroups + `attributeMapping#buldResult`
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, attributeMapping );
sqlSelectionConsumer.accept( sqlSelection );
final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
columnAlias,
state -> new SqlSelectionImpl( valuesArrayPosition, attributeMapping )
),
attributeMapping.getJavaTypeDescriptor(),
domainResultCreationState.getSqlAstCreationState().getCreationContext().getSessionFactory().getTypeConfiguration()
);
return new BasicResult<>(
valuesArrayPosition,

View File

@ -7,7 +7,6 @@
package org.hibernate.query.results.dynamic;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import javax.persistence.AttributeConverter;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -19,7 +18,7 @@ import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ProvidedInstanceManagedBeanImpl;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -97,7 +96,6 @@ public class DynamicResultBuilderBasicConverted<O,R> implements DynamicResultBui
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
final int currentJdbcPosition = resultPosition + 1;
@ -121,8 +119,11 @@ public class DynamicResultBuilderBasicConverted<O,R> implements DynamicResultBui
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
sqlSelectionConsumer.accept( sqlSelection );
final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
sqlExpressionResolver.resolveSqlExpression(
columnAlias,
state -> new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType )
);
//noinspection unchecked
return new BasicResult( valuesArrayPosition, columnAlias, domainJtd, basicValueConverter );

View File

@ -7,13 +7,12 @@
package org.hibernate.query.results.dynamic;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -76,7 +75,6 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
final SessionFactoryImplementor sessionFactory = domainResultCreationState.getSqlAstCreationState()
.getCreationContext()
@ -106,8 +104,15 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
basicType = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
}
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
sqlSelectionConsumer.accept( sqlSelection );
final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
columnName,
state -> new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType )
),
basicType.getJavaTypeDescriptor(),
sessionFactory.getTypeConfiguration()
);
return new BasicResult<>( valuesArrayPosition, resultAlias, explicitJavaTypeDescriptor );
}

View File

@ -7,10 +7,8 @@
package org.hibernate.query.results.dynamic;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.query.results.ResultBuilderEntityValued;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -24,6 +22,5 @@ public interface DynamicResultBuilderEntity extends DynamicResultBuilder, Result
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState);
}

View File

@ -7,16 +7,14 @@
package org.hibernate.query.results.dynamic;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.FromClauseAccessImpl;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.TableGroupImpl;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -54,9 +52,8 @@ public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilde
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
final FromClauseAccessImpl fromClauseAccess = ResultsHelper.extractFromClauseAccess( domainResultCreationState );
final DomainResultCreationStateImpl creationStateImpl = ResultsHelper.impl( domainResultCreationState );
TableGroupImpl.TableReferenceImpl tableReference = new TableGroupImpl.TableReferenceImpl(
entityMapping.getEntityName(),
@ -73,7 +70,7 @@ public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilde
explicitLockMode
);
fromClauseAccess.registerTableGroup( navigablePath, tableGroup );
creationStateImpl.getFromClauseAccess().registerTableGroup( navigablePath, tableGroup );
return (EntityResult) entityMapping.createDomainResult(
navigablePath,

View File

@ -7,14 +7,12 @@
package org.hibernate.query.results.dynamic;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -64,7 +62,6 @@ public class DynamicResultBuilderEntityStandard
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
// final FromClauseAccessImpl fromClauseAccess = ResultsHelper.extractFromClauseAccess( domainResultCreationState );
// final TableGroup tableGroup = fromClauseAccess.resolveTableGroup(

View File

@ -9,13 +9,11 @@ package org.hibernate.query.results.dynamic;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.query.DynamicInstantiationNature;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.results.Builders;
import org.hibernate.query.results.ResultBuilderInstantiationValued;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.instantiation.internal.ArgumentDomainResult;
@ -59,7 +57,6 @@ public class DynamicResultBuilderInstantiation<J>
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) {
if ( argumentResultBuilders.isEmpty() ) {
throw new IllegalStateException( "DynamicResultBuilderInstantiation defined no arguments" );
@ -70,12 +67,11 @@ public class DynamicResultBuilderInstantiation<J>
for ( int i = 0; i < argumentResultBuilders.size(); i++ ) {
final InstantiationArgument argument = argumentResultBuilders.get( i );
final ArgumentDomainResult<Object> argumentDomainResult = new ArgumentDomainResult<>(
final ArgumentDomainResult<?> argumentDomainResult = new ArgumentDomainResult(
argument.argumentBuilder.buildResult(
jdbcResultsMetadata,
i,
legacyFetchResolver,
sqlSelectionConsumer,
domainResultCreationState
)
);

View File

@ -0,0 +1,21 @@
/*
* 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.results.dynamic;
/**
* Contract for handling Hibernate's legacy way of representing fetches through
* {@link org.hibernate.query.NativeQuery#addFetch}, {@link org.hibernate.query.NativeQuery#addJoin},
* `hbm.xml` mappings, etc
*
* @see org.hibernate.query.results.DomainResultCreationStateImpl#getLegacyFetchResolver()
*
* @author Steve Ebersole
*/
@FunctionalInterface
public interface LegacyFetchResolver {
DynamicFetchBuilderLegacy resolve(String ownerTableAlias, String fetchedPartPath);
}

View File

@ -63,9 +63,9 @@ import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.results.Builders;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.ResultSetMappingImpl;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.query.results.dynamic.DynamicResultBuilderEntityStandard;
import org.hibernate.query.results.dynamic.DynamicResultBuilderInstantiation;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.query.spi.AbstractQuery;
import org.hibernate.query.spi.MutableQueryOptions;
import org.hibernate.query.spi.NonSelectQueryPlan;
@ -105,12 +105,12 @@ public class NativeQueryImpl<R>
private final List<QueryParameterImplementor<?>> occurrenceOrderedParamList;
private final QueryParameterBindings parameterBindings;
private final ResultSetMappingImpl resultSetMapping;
private final QueryOptionsImpl queryOptions = new QueryOptionsImpl();
private Set<String> querySpaces;
private ResultSetMappingImpl resultSetMapping = new ResultSetMappingImpl();
private Object collectionKey;
private NativeQueryInterpreter nativeQueryInterpreter;
@ -125,11 +125,30 @@ public class NativeQueryImpl<R>
this.sqlString = memento.getSqlString();
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session );
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.resultSetMapping = new ResultSetMappingImpl( sqlString );
applyOptions( memento );
}
private NativeQueryImpl(
String resultMappingIdentifier,
NamedNativeQueryMemento memento,
SharedSessionContractImplementor session) {
super( session );
this.sqlString = memento.getSqlString();
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session );
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.resultSetMapping = new ResultSetMappingImpl( resultMappingIdentifier );
applyOptions( memento );
}
@ -155,7 +174,7 @@ public class NativeQueryImpl<R>
NamedNativeQueryMemento memento,
String resultSetMappingName,
SharedSessionContractImplementor session) {
this( memento, session );
this( resultSetMappingName, memento, session );
session.getFactory()
.getQueryEngine()
@ -171,6 +190,8 @@ public class NativeQueryImpl<R>
super( session );
this.sqlString = sqlString;
this.resultSetMapping = new ResultSetMappingImpl( resultSetMappingMemento.getName() );
resultSetMappingMemento.resolve( resultSetMapping, (s) -> {}, this );
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session );
@ -231,6 +252,8 @@ public class NativeQueryImpl<R>
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.resultSetMapping = new ResultSetMappingImpl( sqlString );
}
@Override

View File

@ -28,6 +28,7 @@ import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.internal.util.collections.StandardStack;
import org.hibernate.loader.MultipleBagFetchException;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPart;
@ -294,12 +295,16 @@ public class StandardSqmSelectTranslator
final Fetch fetch = buildFetch( fetchablePath, fetchParent, fetchable, isKeyFetchable );
if ( fetch != null ) {
if ( fetch.getTiming() == FetchTiming.IMMEDIATE &&
fetchable instanceof PluralAttributeMapping &&
( (PluralAttributeMapping) fetchable ).getMappedTypeDescriptor()
.getCollectionSemantics() instanceof BagSemantics ) {
bagRoles.add( fetchable.getNavigableRole().getNavigableName() );
if ( fetch.getTiming() == FetchTiming.IMMEDIATE && fetchable instanceof PluralAttributeMapping ) {
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) fetchable;
final CollectionClassification collectionClassification = pluralAttributeMapping.getMappedTypeDescriptor()
.getCollectionSemantics()
.getCollectionClassification();
if ( collectionClassification == CollectionClassification.BAG ) {
bagRoles.add( fetchable.getNavigableRole().getNavigableName() );
}
}
fetches.add( fetch );
}
}

View File

@ -17,6 +17,13 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
* @author Steve Ebersole
*/
public interface DomainResultGraphNode {
/**
* Does this node contain any non-scalar (sub-)results?
*/
default boolean containsAnyNonScalarResults() {
return false;
}
// todo (6.0) : result variable (selection alias)? - even fetches can have alias
JavaTypeDescriptor getResultJavaTypeDescriptor();

View File

@ -56,8 +56,13 @@ public interface Fetch extends DomainResultGraphNode {
*/
boolean hasTableGroup();
@Override
default boolean containsAnyNonScalarResults() {
return true;
}
/**
* Create the assembler for this fetch
*/
DomainResultAssembler createAssembler(FetchParentAccess parentAccess, AssemblerCreationState creationState);
DomainResultAssembler<?> createAssembler(FetchParentAccess parentAccess, AssemblerCreationState creationState);
}

View File

@ -73,6 +73,11 @@ public class CollectionDomainResult implements DomainResult, CollectionResultGra
return resultVariable;
}
@Override
public boolean containsAnyNonScalarResults() {
return true;
}
@Override
public JavaTypeDescriptor getResultJavaTypeDescriptor() {
return loadingAttribute.getJavaTypeDescriptor();

View File

@ -61,6 +61,11 @@ public class EmbeddableForeignKeyResultImpl<T>
);
}
@Override
public boolean containsAnyNonScalarResults() {
return true;
}
private void generateFetches(
List<SqlSelection> sqlSelections,
NavigablePath navigablePath,

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.sql.results.graph.embeddable.internal;
import java.util.List;
import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
@ -18,6 +20,8 @@ import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.DomainResultGraphNode;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer;
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -27,6 +31,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
*/
public class EmbeddableResultImpl<T> extends AbstractFetchParent implements EmbeddableResultGraphNode, DomainResult<T> {
private final String resultVariable;
private final boolean containsAnyNonScalars;
public EmbeddableResultImpl(
NavigablePath navigablePath,
@ -56,6 +61,19 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
);
afterInitialize( creationState );
// after-after-initialize :D
containsAnyNonScalars = determineIfContainedAnyScalars( fetches );
}
private static boolean determineIfContainedAnyScalars(List<Fetch> fetches) {
for ( int i = 0; i < fetches.size(); i++ ) {
if ( fetches.get( i ).containsAnyNonScalarResults() ) {
return true;
}
}
return false;
}
@Override
@ -63,6 +81,11 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
return resultVariable;
}
@Override
public boolean containsAnyNonScalarResults() {
return containsAnyNonScalars;
}
@Override
public EmbeddableMappingType getFetchContainer() {
return (EmbeddableMappingType) super.getFetchContainer();

View File

@ -12,4 +12,8 @@ import org.hibernate.sql.results.graph.Fetch;
* @author Steve Ebersole
*/
public interface EntityFetch extends EntityResultGraphNode, Fetch {
@Override
default boolean containsAnyNonScalarResults() {
return true;
}
}

View File

@ -23,6 +23,10 @@ public interface EntityResultGraphNode extends DomainResultGraphNode, FetchParen
NavigablePath getNavigablePath();
EntityValuedModelPart getEntityValuedModelPart();
@Override
default boolean containsAnyNonScalarResults() {
return true;
}
@Override
default JavaTypeDescriptor getResultJavaTypeDescriptor() {

View File

@ -14,9 +14,9 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
* @author Steve Ebersole
*/
public class ArgumentDomainResult<A> implements DomainResult<A> {
private final DomainResult realDomainResult;
private final DomainResult<A> realDomainResult;
public ArgumentDomainResult(DomainResult realDomainResult) {
public ArgumentDomainResult(DomainResult<A> realDomainResult) {
this.realDomainResult = realDomainResult;
}
@ -26,15 +26,19 @@ public class ArgumentDomainResult<A> implements DomainResult<A> {
}
@Override
public boolean containsAnyNonScalarResults() {
return realDomainResult.containsAnyNonScalarResults();
}
@Override
@SuppressWarnings("rawtypes")
public JavaTypeDescriptor getResultJavaTypeDescriptor() {
return realDomainResult.getResultJavaTypeDescriptor();
}
@Override
public ArgumentReader<A> createResultAssembler(
AssemblerCreationState creationState) {
//noinspection unchecked
return new ArgumentReader(
public ArgumentReader<A> createResultAssembler(AssemblerCreationState creationState) {
return new ArgumentReader<>(
realDomainResult.createResultAssembler( creationState ),
getResultVariable()
);

View File

@ -22,12 +22,12 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
public class DynamicInstantiationAssemblerConstructorImpl<R> implements DomainResultAssembler<R> {
private final Constructor<R> targetConstructor;
private final JavaTypeDescriptor<R> resultType;
private final List<ArgumentReader> argumentReaders;
private final List<ArgumentReader<?>> argumentReaders;
public DynamicInstantiationAssemblerConstructorImpl(
Constructor<R> targetConstructor,
JavaTypeDescriptor<R> resultType,
List<ArgumentReader> argumentReaders) {
List<ArgumentReader<?>> argumentReaders) {
this.targetConstructor = targetConstructor;
this.resultType = resultType;
this.argumentReaders = argumentReaders;

View File

@ -14,8 +14,6 @@ import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.jboss.logging.Logger;
/**
* A QueryResultAssembler implementation representing handling for dynamic-
* instantiations targeting a List (per-"row"),
@ -24,30 +22,28 @@ import org.jboss.logging.Logger;
*
* @author Steve Ebersole
*/
public class DynamicInstantiationAssemblerListImpl implements DomainResultAssembler<List> {
private static final Logger log = Logger.getLogger( DynamicInstantiationAssemblerListImpl.class );
private final JavaTypeDescriptor<List> listJavaDescriptor;
public class DynamicInstantiationAssemblerListImpl implements DomainResultAssembler<List<?>> {
private final JavaTypeDescriptor<List<?>> listJavaDescriptor;
private final List<ArgumentReader<?>> argumentReaders;
public DynamicInstantiationAssemblerListImpl(
JavaTypeDescriptor<List> listJavaDescriptor,
JavaTypeDescriptor<List<?>> listJavaDescriptor,
List<ArgumentReader<?>> argumentReaders) {
this.listJavaDescriptor = listJavaDescriptor;
this.argumentReaders = argumentReaders;
}
@Override
public JavaTypeDescriptor<List> getAssembledJavaTypeDescriptor() {
public JavaTypeDescriptor<List<?>> getAssembledJavaTypeDescriptor() {
return listJavaDescriptor;
}
@Override
public List assemble(
public List<?> assemble(
RowProcessingState rowProcessingState,
JdbcValuesSourceProcessingOptions options) {
final ArrayList<Object> result = new ArrayList<>();
for ( ArgumentReader argumentReader : argumentReaders ) {
for ( ArgumentReader<?> argumentReader : argumentReaders ) {
result.add( argumentReader.assemble( rowProcessingState, options ) );
}
return result;

View File

@ -24,18 +24,18 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
*
* @author Steve Ebersole
*/
public class DynamicInstantiationAssemblerMapImpl implements DomainResultAssembler<Map> {
private final JavaTypeDescriptor<Map> mapJavaDescriptor;
public class DynamicInstantiationAssemblerMapImpl implements DomainResultAssembler<Map<?,?>> {
private final JavaTypeDescriptor<Map<?,?>> mapJavaDescriptor;
private final List<ArgumentReader<?>> argumentReaders;
public DynamicInstantiationAssemblerMapImpl(
JavaTypeDescriptor<Map> mapJavaDescriptor,
JavaTypeDescriptor<Map<?,?>> mapJavaDescriptor,
List<ArgumentReader<?>> argumentReaders) {
this.mapJavaDescriptor = mapJavaDescriptor;
this.argumentReaders = argumentReaders;
final Set<String> aliases = new HashSet<>();
for ( ArgumentReader argumentReader : argumentReaders ) {
for ( ArgumentReader<?> argumentReader : argumentReaders ) {
if ( argumentReader.getAlias() == null ) {
throw new IllegalStateException( "alias for Map dynamic instantiation argument cannot be null" );
}
@ -48,17 +48,17 @@ public class DynamicInstantiationAssemblerMapImpl implements DomainResultAssembl
}
@Override
public JavaTypeDescriptor<Map> getAssembledJavaTypeDescriptor() {
public JavaTypeDescriptor<Map<?,?>> getAssembledJavaTypeDescriptor() {
return mapJavaDescriptor;
}
@Override
public Map assemble(
public Map<?,?> assemble(
RowProcessingState rowProcessingState,
JdbcValuesSourceProcessingOptions options) {
final HashMap<String,Object> result = new HashMap<>();
for ( ArgumentReader argumentReader : argumentReaders ) {
for ( ArgumentReader<?> argumentReader : argumentReaders ) {
result.put(
argumentReader.getAlias(),
argumentReader.assemble( rowProcessingState, options )

View File

@ -10,6 +10,7 @@ import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.internal.util.StringHelper;
@ -32,13 +33,13 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
private final DynamicInstantiationNature nature;
private final JavaTypeDescriptor<R> javaTypeDescriptor;
private final List<ArgumentDomainResult> argumentResults;
private final List<ArgumentDomainResult<?>> argumentResults;
public DynamicInstantiationResultImpl(
String resultVariable,
DynamicInstantiationNature nature,
JavaTypeDescriptor<R> javaTypeDescriptor,
List<ArgumentDomainResult> argumentResults) {
List<ArgumentDomainResult<?>> argumentResults) {
this.resultVariable = resultVariable;
this.nature = nature;
this.javaTypeDescriptor = javaTypeDescriptor;
@ -46,7 +47,7 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
}
@Override
public JavaTypeDescriptor getResultJavaTypeDescriptor() {
public JavaTypeDescriptor<R> getResultJavaTypeDescriptor() {
return javaTypeDescriptor;
}
@ -55,6 +56,19 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
return resultVariable;
}
@Override
public boolean containsAnyNonScalarResults() {
//noinspection ForLoopReplaceableByForEach
for ( int i = 0; i < argumentResults.size(); i++ ) {
final ArgumentDomainResult<?> argumentResult = argumentResults.get( i );
if ( argumentResult.containsAnyNonScalarResults() ) {
return true;
}
}
return false;
}
@Override
public DomainResultAssembler<R> createResultAssembler(AssemblerCreationState creationState) {
boolean areAllArgumentsAliased = true;
@ -64,7 +78,7 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
final List<ArgumentReader<?>> argumentReaders = new ArrayList<>();
if ( argumentResults != null ) {
for ( ArgumentDomainResult argumentResult : argumentResults ) {
for ( ArgumentDomainResult<?> argumentResult : argumentResults ) {
final String argumentAlias = argumentResult.getResultVariable();
if ( argumentAlias == null ) {
areAllArgumentsAliased = false;
@ -107,7 +121,7 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
log.debug( "One or more arguments for List dynamic instantiation (`new list(...)`) specified an alias; ignoring" );
}
return (DomainResultAssembler<R>) new DynamicInstantiationAssemblerListImpl(
(JavaTypeDescriptor<List>) javaTypeDescriptor,
(JavaTypeDescriptor<List<?>>) javaTypeDescriptor,
argumentReaders
);
}
@ -121,21 +135,21 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
);
}
return (DomainResultAssembler<R>) new DynamicInstantiationAssemblerMapImpl(
(JavaTypeDescriptor) javaTypeDescriptor,
(JavaTypeDescriptor<Map<?,?>>) javaTypeDescriptor,
argumentReaders
);
}
else {
// find a constructor matching argument types
constructor_loop:
for ( Constructor constructor : javaTypeDescriptor.getJavaType().getDeclaredConstructors() ) {
for ( Constructor<?> constructor : javaTypeDescriptor.getJavaType().getDeclaredConstructors() ) {
if ( constructor.getParameterTypes().length != argumentReaders.size() ) {
continue;
}
for ( int i = 0; i < argumentReaders.size(); i++ ) {
final ArgumentReader argumentReader = argumentReaders.get( i );
final JavaTypeDescriptor argumentTypeDescriptor = creationState.getSqlAstCreationContext()
final ArgumentReader<?> argumentReader = argumentReaders.get( i );
final JavaTypeDescriptor<?> argumentTypeDescriptor = creationState.getSqlAstCreationContext()
.getDomainModel()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
@ -159,6 +173,7 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
}
constructor.setAccessible( true );
//noinspection rawtypes
return new DynamicInstantiationAssemblerConstructorImpl(
constructor,
javaTypeDescriptor,
@ -185,7 +200,10 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
);
}
return new DynamicInstantiationAssemblerInjectionImpl( javaTypeDescriptor, argumentReaders );
return new DynamicInstantiationAssemblerInjectionImpl<>(
javaTypeDescriptor,
argumentReaders
);
}
}
}

View File

@ -0,0 +1,17 @@
/*
* 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.sql.results.graph.instantiation.internal;
/**
* @author Steve Ebersole
*/
public class InstantiationHelper {
private InstantiationHelper() {
// disallow direct instantiation
}
}

View File

@ -6,10 +6,12 @@
*/
package org.hibernate.orm.test.query.named.resultmapping;
import javax.persistence.Basic;
import javax.persistence.ColumnResult;
import javax.persistence.ConstructorResult;
import javax.persistence.Entity;
import javax.persistence.EntityResult;
import javax.persistence.FetchType;
import javax.persistence.FieldResult;
import javax.persistence.Id;
import javax.persistence.SqlResultSetMapping;
@ -40,7 +42,7 @@ import javax.persistence.SqlResultSetMapping;
)
)
@SqlResultSetMapping(
name = "entity",
name = "entity-id-name",
entities = @EntityResult(
entityClass = SimpleEntityWithNamedMappings.class,
fields = {
@ -49,18 +51,45 @@ import javax.persistence.SqlResultSetMapping;
}
)
)
@SqlResultSetMapping(
name = "entity-id-notes",
entities = @EntityResult(
entityClass = SimpleEntityWithNamedMappings.class,
fields = {
@FieldResult( name = "id", column = "id" ),
@FieldResult( name = "notes", column = "notes" )
}
)
)
@SqlResultSetMapping(
name = "entity",
entities = @EntityResult(
entityClass = SimpleEntityWithNamedMappings.class,
fields = {
@FieldResult( name = "id", column = "id" ),
@FieldResult( name = "name", column = "name" ),
@FieldResult( name = "notes", column = "notes" )
}
)
)
public class SimpleEntityWithNamedMappings {
@Id
private Integer id;
private String name;
private String notes;
protected SimpleEntityWithNamedMappings() {
}
public SimpleEntityWithNamedMappings(Integer id, String name) {
this( id, name, null );
}
public SimpleEntityWithNamedMappings(Integer id, String name, String notes) {
this.id = id;
this.name = name;
this.notes = notes;
}
public Integer getId() {
@ -79,6 +108,15 @@ public class SimpleEntityWithNamedMappings {
this.name = name;
}
@Basic( fetch = FetchType.LAZY )
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public static class DropDownDto {
private final Integer id;
private final String text;

View File

@ -34,7 +34,7 @@ public class SimpleNamedMappingTests {
final NamedQueryRepository namedQueryRepository = queryEngine.getNamedQueryRepository();
final NamedResultSetMappingMemento mappingMemento = namedQueryRepository.getResultSetMappingMemento( "name" );
final ResultSetMapping mapping = new ResultSetMappingImpl();
final ResultSetMapping mapping = new ResultSetMappingImpl( "test" );
final ResultSetMappingResolutionContext resolutionContext = new ResultSetMappingResolutionContext() {
@Override

View File

@ -78,7 +78,6 @@ public class UsageTests {
}
@Test
@FailureExpected( reason = "Entity result mappings not yet implemented" )
public void testSimpleEntityResultMapping(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
@ -90,7 +89,7 @@ public class UsageTests {
assertThat( mappingMemento, notNullValue() );
// apply it to a native-query
final String qryString = "select id, name from SimpleEntityWithNamedMappings";
final String qryString = "select id, name, notes from SimpleEntityWithNamedMappings";
final List<SimpleEntityWithNamedMappings> results
= session.createNativeQuery( qryString, "entity" ).list();
assertThat( results.size(), is( 1 ) );