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; 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.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.named.ResultMemento;
/** /**
* Describes the mapping for a fetch as part of a {@link NamedResultSetMappingDescriptor} * 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 * Resolve the descriptor into a memento capable of being stored in the
* {@link org.hibernate.query.named.NamedQueryRepository} * {@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.LockMode;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.internal.ResultSetMappingResolutionContext; 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.query.named.NamedResultSetMappingMemento;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
@ -58,7 +58,7 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
@Override @Override
public NamedResultSetMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) { public NamedResultSetMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
final List<ScalarResultMappingMemento> scalarResultMementos; final List<ResultMementoBasicStandard> scalarResultMementos;
if ( scalarResultMappings == null || scalarResultMappings.isEmpty() ) { if ( scalarResultMappings == null || scalarResultMappings.isEmpty() ) {
scalarResultMementos = Collections.emptyList(); scalarResultMementos = Collections.emptyList();
} }
@ -148,7 +148,7 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
} }
@Override @Override
public ScalarResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) { public ResultMementoBasicStandard resolve(ResultSetMappingResolutionContext resolutionContext) {
if ( hibernateTypeName != null ) { if ( hibernateTypeName != null ) {
final BasicType<?> namedType = resolutionContext.getSessionFactory() final BasicType<?> namedType = resolutionContext.getSessionFactory()
.getTypeConfiguration() .getTypeConfiguration()
@ -159,12 +159,12 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
throw new IllegalArgumentException( "Could not resolve named type : " + hibernateTypeName ); 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 // 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; 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.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.named.NamedResultSetMappingMemento; import org.hibernate.query.named.NamedResultSetMappingMemento;

View File

@ -6,7 +6,7 @@
*/ */
package org.hibernate.boot.query; package org.hibernate.boot.query;
import org.hibernate.query.internal.ResultMappingMemento; import org.hibernate.query.named.ResultMemento;
import org.hibernate.query.internal.ResultSetMappingResolutionContext; 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 * Resolve the descriptor into a memento capable of being stored in the
* {@link org.hibernate.query.named.NamedQueryRepository} * {@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.FieldResult;
import javax.persistence.SqlResultSetMapping; import javax.persistence.SqlResultSetMapping;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.BootLogging; import org.hibernate.boot.BootLogging;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.MutableObject;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.RuntimeMetamodels; import org.hibernate.metamodel.RuntimeMetamodels;
import org.hibernate.metamodel.mapping.BasicValuedModelPart; 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.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPart; 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.NavigablePath;
import org.hibernate.query.internal.BasicFetchMemento; import org.hibernate.query.internal.FetchMementoBasicStandard;
import org.hibernate.query.internal.EntityResultMappingMemento; import org.hibernate.query.internal.ModelPartResultMementoBasicImpl;
import org.hibernate.query.internal.FetchMappingMemento;
import org.hibernate.query.internal.InstantiationResultMappingMemento;
import org.hibernate.query.internal.InstantiationResultMappingMemento.ArgumentMemento;
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl; 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.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.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; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/** /**
@ -74,7 +83,7 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
for ( int i = 0; i < entityResults.length; i++ ) { for ( int i = 0; i < entityResults.length; i++ ) {
final EntityResult entityResult = entityResults[i]; final EntityResult entityResult = entityResults[i];
resultDescriptors.add( resultDescriptors.add(
EntityResultDescriptor.from( entityResult, context ) new EntityResultDescriptor( entityResult, mappingAnnotation, context )
); );
} }
@ -117,7 +126,7 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
@Override @Override
public NamedResultSetMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) { public NamedResultSetMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
final List<ResultMappingMemento> resultMementos = CollectionHelper.arrayList( resultDescriptors.size() ); final List<ResultMemento> resultMementos = CollectionHelper.arrayList( resultDescriptors.size() );
resultDescriptors.forEach( resultDescriptors.forEach(
resultDescriptor -> resultMementos.add( resultDescriptor.resolve( resolutionContext ) ) resultDescriptor -> resultMementos.add( resultDescriptor.resolve( resolutionContext ) )
@ -142,14 +151,14 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
} }
@Override @Override
public ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) { public ResultMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
BootLogging.LOGGER.debugf( BootLogging.LOGGER.debugf(
"Generating ScalarResultMappingMemento for JPA ColumnResult(%s) for ResultSet mapping `%s`", "Generating ScalarResultMappingMemento for JPA ColumnResult(%s) for ResultSet mapping `%s`",
columnResult.name(), columnResult.name(),
mappingName mappingName
); );
return new ScalarResultMappingMemento( columnResult, resolutionContext ); return new ResultMementoBasicStandard( columnResult, resolutionContext );
} }
} }
@ -197,7 +206,7 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
} }
@Override @Override
public ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) { public ResultMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
BootLogging.LOGGER.debugf( BootLogging.LOGGER.debugf(
"Generating InstantiationResultMappingMemento for JPA ConstructorResult(%s) for ResultSet mapping `%s`", "Generating InstantiationResultMappingMemento for JPA ConstructorResult(%s) for ResultSet mapping `%s`",
targetJavaType.getName(), targetJavaType.getName(),
@ -215,7 +224,7 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
.getJavaTypeDescriptorRegistry() .getJavaTypeDescriptorRegistry()
.getDescriptor( targetJavaType ); .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 * @see javax.persistence.EntityResult
*/ */
public static class EntityResultDescriptor implements ResultDescriptor { public static class EntityResultDescriptor implements ResultDescriptor {
private final NavigablePath navigablePath; private String resultSetMappingName;
private final NavigablePath navigablePath;
private final String entityName; private final String entityName;
private final String discriminatorColumn; private final String discriminatorColumn;
private final Map<String, AttributeFetchDescriptor> fetchMappings; private final Map<String, AttributeFetchDescriptor> fetchMappings;
public static EntityResultDescriptor from(EntityResult entityResult, MetadataBuildingContext context) { public EntityResultDescriptor(
final String entityName = entityResult.entityClass().getName(); 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++ ) { for ( int i = 0; i < entityResult.fields().length; i++ ) {
final FieldResult fieldResult = entityResult.fields()[ i ]; final FieldResult fieldResult = entityResult.fields()[ i ];
final AttributeFetchDescriptor existing = fetchMappings.get( fieldResult.name() ); final AttributeFetchDescriptor existing = fetchMappings.get( fieldResult.name() );
@ -243,62 +260,107 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
else { else {
fetchMappings.put( fetchMappings.put(
fieldResult.name(), 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 @Override
public ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) { public ResultMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels(); final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels();
final EntityMappingType entityDescriptor = runtimeMetamodels.getEntityMappingType( entityName ); 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<>(); final MutableObject<ResultMemento> identifierMementoReference = new MutableObject<>();
fetchMappings.forEach(
(attrName, attrMapping) -> fetchMementos.put( attrName, attrMapping.resolve( resolutionContext ) ) 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 class AttributeFetchDescriptor implements FetchDescriptor {
private static AttributeFetchDescriptor from( private static AttributeFetchDescriptor from(
NavigablePath entityPath,
String entityName, String entityName,
FieldResult fieldResult, FieldResult fieldResult,
MetadataBuildingContext context) { MetadataBuildingContext context) {
return new AttributeFetchDescriptor( return new AttributeFetchDescriptor(
entityPath.append( fieldResult.name() ),
entityName, entityName,
fieldResult.name(), fieldResult.name(),
fieldResult.column() fieldResult.column()
); );
} }
private final NavigablePath navigablePath;
private final String entityName; private final String entityName;
private final String attributeName; private final String attributeName;
private final List<String> columnNames; 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.entityName = entityName;
this.attributeName = attributeName; this.attributeName = attributeName;
this.columnNames = new ArrayList<>(); this.columnNames = new ArrayList<>();
@ -322,7 +384,9 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
} }
@Override @Override
public FetchMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) { public ResultMemento asResultMemento(
NavigablePath path,
ResultSetMappingResolutionContext resolutionContext) {
final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels(); final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels();
final EntityMappingType entityMapping = runtimeMetamodels.getEntityMappingType( entityName ); final EntityMappingType entityMapping = runtimeMetamodels.getEntityMappingType( entityName );
@ -336,7 +400,34 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
assert columnNames.size() == 1; assert columnNames.size() == 1;
final BasicValuedModelPart basicPart = (BasicValuedModelPart) subPart; 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( throw new NotYetImplementedFor6Exception(

View File

@ -6,6 +6,13 @@
*/ */
package org.hibernate.internal.util; 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 { public class MutableLong {
private long value; 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 * @author Steve Ebersole
*/ */
public interface EntityMappingType extends ManagedMappingType, Loadable { public interface EntityMappingType extends ManagedMappingType, EntityValuedModelPart, Loadable {
/** /**
* Safety-net. * Safety-net.
* *

View File

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

View File

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

View File

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

View File

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

View File

@ -77,7 +77,7 @@ import org.hibernate.type.VersionType;
* @see org.hibernate.persister.spi.PersisterFactory * @see org.hibernate.persister.spi.PersisterFactory
* @see org.hibernate.persister.spi.PersisterClassResolver * @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 * 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.RootGraph;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.model.domain.AllowableParameterType; import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
@ -84,7 +85,7 @@ public class ProcedureCallImpl<R>
private final ProcedureParameterMetadataImpl parameterMetadata; private final ProcedureParameterMetadataImpl parameterMetadata;
private final ProcedureParamBindings paramBindings; private final ProcedureParamBindings paramBindings;
private final ResultSetMapping resultSetMapping = new ResultSetMappingImpl(); private final ResultSetMapping resultSetMapping;
private Set<String> synchronizedQuerySpaces; private Set<String> synchronizedQuerySpaces;
@ -106,6 +107,8 @@ public class ProcedureCallImpl<R>
this.parameterMetadata = new ProcedureParameterMetadataImpl(); this.parameterMetadata = new ProcedureParameterMetadataImpl();
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() ); this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
this.resultSetMapping = new ResultSetMappingImpl( procedureName );
this.synchronizedQuerySpaces = null; this.synchronizedQuerySpaces = null;
} }
/** /**
@ -127,6 +130,10 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = new HashSet<>(); this.synchronizedQuerySpaces = new HashSet<>();
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultClasses );
this.resultSetMapping = new ResultSetMappingImpl( mappingId );
Util.resolveResultSetMappingClasses( Util.resolveResultSetMappingClasses(
resultClasses, resultClasses,
resultSetMapping, resultSetMapping,
@ -157,6 +164,9 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = new HashSet<>(); this.synchronizedQuerySpaces = new HashSet<>();
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultSetMappingNames );
this.resultSetMapping = new ResultSetMappingImpl( mappingId );
Util.resolveResultSetMappingNames( Util.resolveResultSetMappingNames(
resultSetMappingNames, resultSetMappingNames,
resultSetMapping, resultSetMapping,
@ -181,6 +191,8 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() ); this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
this.resultSetMapping = new ResultSetMappingImpl( memento.getRegistrationName() );
Util.resolveResultSetMappings( Util.resolveResultSetMappings(
memento.getResultSetMappingNames(), memento.getResultSetMappingNames(),
memento.getResultSetMappingClasses(), memento.getResultSetMappingClasses(),
@ -211,6 +223,9 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() ); this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultTypes );
this.resultSetMapping = new ResultSetMappingImpl( mappingId );
Util.resolveResultSetMappings( Util.resolveResultSetMappings(
null, null,
resultTypes, resultTypes,
@ -235,6 +250,9 @@ public class ProcedureCallImpl<R>
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() ); this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
final String mappingId = procedureName + ":" + StringHelper.join( ",", resultSetMappingNames );
this.resultSetMapping = new ResultSetMappingImpl( mappingId );
Util.resolveResultSetMappings( Util.resolveResultSetMappings(
resultSetMappingNames, resultSetMappingNames,
null, 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 java.util.function.Consumer;
import org.hibernate.metamodel.mapping.BasicValuedModelPart; 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.FetchBuilder;
import org.hibernate.query.results.complete.CompleteFetchBuilderBasicPart; import org.hibernate.query.results.complete.CompleteFetchBuilderBasicPart;
@ -18,20 +22,40 @@ import org.hibernate.query.results.complete.CompleteFetchBuilderBasicPart;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class BasicFetchMemento implements FetchMappingMemento { public class FetchMementoBasicStandard implements FetchMementoBasic {
private final NavigablePath navigablePath;
private final BasicValuedModelPart fetchedAttribute; private final BasicValuedModelPart fetchedAttribute;
private final String columnAlias; 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.fetchedAttribute = fetchedAttribute;
this.columnAlias = columnAlias; this.columnAlias = columnAlias;
} }
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public ModelPart getReferencedModelPart() {
return fetchedAttribute;
}
@Override
public MappingType getMappingType() {
return fetchedAttribute.getPartMappingType();
}
@Override @Override
public FetchBuilder resolve( public FetchBuilder resolve(
Parent parent, Parent parent,
Consumer<String> querySpaceConsumer, Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context) { 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 java.util.function.Consumer;
import org.hibernate.query.named.NamedResultSetMappingMemento; import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.named.ResultMemento;
import org.hibernate.query.results.ResultSetMapping; import org.hibernate.query.results.ResultSetMapping;
/** /**
@ -19,13 +20,13 @@ import org.hibernate.query.results.ResultSetMapping;
*/ */
public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMemento { public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMemento {
private final String name; private final String name;
private final List<ResultMappingMemento> resultMappingMementos; private final List<ResultMemento> resultMementos;
public NamedResultSetMappingMementoImpl( public NamedResultSetMappingMementoImpl(
String name, String name,
List<ResultMappingMemento> resultMappingMementos) { List<ResultMemento> resultMementos) {
this.name = name; this.name = name;
this.resultMappingMementos = resultMappingMementos; this.resultMementos = resultMementos;
} }
@Override @Override
@ -38,7 +39,7 @@ public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMe
ResultSetMapping resultSetMapping, ResultSetMapping resultSetMapping,
Consumer<String> querySpaceConsumer, Consumer<String> querySpaceConsumer,
ResultSetMappingResolutionContext context) { ResultSetMappingResolutionContext context) {
resultMappingMementos.forEach( resultMementos.forEach(
memento -> resultSetMapping.addResultBuilder( memento.resolve( querySpaceConsumer, context ) ) memento -> resultSetMapping.addResultBuilder( memento.resolve( querySpaceConsumer, context ) )
); );
} }

View File

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

View File

@ -4,30 +4,34 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.query.internal; package org.hibernate.query.named;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.metamodel.mapping.ManagedMappingType; 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; import org.hibernate.query.results.FetchBuilder;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface FetchMappingMemento { public interface FetchMemento extends ModelPartReferenceMemento {
interface Parent { /**
/** * The parent node for the fetch
* The path for the parent */
*/ interface Parent extends ModelPartReferenceMemento {
NavigablePath getNavigablePath();
/** /**
* The entity descriptor that is the base for this path/parent * The entity descriptor that is the base for this path/parent
*/ */
ManagedMappingType getMappingType(); ManagedMappingType getMappingType();
} }
/**
* The mapping descriptor for the fetchable
*/
MappingType getMappingType();
/** /**
* Resolve the fetch-memento into the result-graph-node builder * 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 * License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/ */
package org.hibernate.query.internal; package org.hibernate.query.named;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.Incubating;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.results.ResultBuilder; import org.hibernate.query.results.ResultBuilder;
/** /**
* @since 6.0
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface ResultMappingMemento { @Incubating
public interface ResultMemento extends ResultMappingMementoNode {
ResultBuilder resolve(Consumer<String> querySpaceConsumer, ResultSetMappingResolutionContext context); 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.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; 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.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.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.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class DomainResultCreationStateImpl implements DomainResultCreationState { @Internal
private final List<ResultBuilder> resultBuilders; public class DomainResultCreationStateImpl
private final Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders; implements DomainResultCreationState, SqlAstCreationState, SqlAstProcessingState, SqlExpressionResolver {
private final SqlAstCreationStateImpl sqlAstCreationState;
private final String stateIdentifier;
private final FromClauseAccessImpl fromClauseAccess; 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 LegacyFetchResolverImpl legacyFetchResolver;
private final SessionFactoryImplementor sessionFactory;
public DomainResultCreationStateImpl( public DomainResultCreationStateImpl(
List<ResultBuilder> resultBuilders, String stateIdentifier,
Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders, Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders,
Consumer<SqlSelection> sqlSelectionConsumer,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
this.resultBuilders = resultBuilders; this.stateIdentifier = stateIdentifier;
this.legacyFetchBuilders = legacyFetchBuilders; this.sqlSelectionConsumer = sqlSelectionConsumer;
this.fromClauseAccess = new FromClauseAccessImpl(); 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() { public FromClauseAccessImpl getFromClauseAccess() {
return fromClauseAccess; return fromClauseAccess;
} }
@Override @Override
public SqlAstCreationStateImpl getSqlAstCreationState() { public DomainResultCreationStateImpl getSqlAstCreationState() {
return sqlAstCreationState; return this;
} }
@FunctionalInterface @Override
public interface LegacyFetchResolver { public SqlAliasBaseManager getSqlAliasBaseManager() {
DynamicFetchBuilderLegacy resolve(String ownerTableAlias, String fetchedPartPath); 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 static class LegacyFetchResolverImpl implements LegacyFetchResolver {
private final Map<String,Map<String, DynamicFetchBuilderLegacy>> legacyFetchResolvers; private final Map<String,Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders;
public LegacyFetchResolverImpl() { public LegacyFetchResolverImpl(Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders) {
this.legacyFetchResolvers = new HashMap<>(); this.legacyFetchBuilders = legacyFetchBuilders;
} }
@Override @Override
public DynamicFetchBuilderLegacy resolve(String ownerTableAlias, String fetchedPartPath) { 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 ) { if ( fetchBuilders == null ) {
return null; return null;
} }
@ -71,10 +244,6 @@ public class DomainResultCreationStateImpl implements DomainResultCreationState
} }
} }
public LegacyFetchResolver getLegacyFetchResolver() {
return legacyFetchResolver;
}
@Override @Override
public List<Fetch> visitFetches(FetchParent fetchParent) { public List<Fetch> visitFetches(FetchParent fetchParent) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View File

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

View File

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

View File

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

View File

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

View File

@ -24,18 +24,6 @@ public class ResultsHelper {
return unwrap( creationState ); 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) { private static DomainResultCreationStateImpl unwrap(DomainResultCreationState creationState) {
if ( creationState instanceof DomainResultCreationStateImpl ) { if ( creationState instanceof DomainResultCreationStateImpl ) {
return ( (DomainResultCreationStateImpl) creationState ); return ( (DomainResultCreationStateImpl) creationState );

View File

@ -6,44 +6,83 @@
*/ */
package org.hibernate.query.results; 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.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor; 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.SqlAliasBaseGenerator;
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState; 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 * SqlAstCreationState implementation for result-set mapping handling
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SqlAstCreationStateImpl implements SqlAstCreationState { @Internal
private final SessionFactoryImplementor sessionFactory; public class SqlAstCreationStateImpl implements SqlAstCreationState, SqlAstProcessingState, SqlExpressionResolver {
private final FromClauseAccessImpl fromClauseAccess; 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( public SqlAstCreationStateImpl(
FromClauseAccessImpl fromClauseAccess, FromClauseAccessImpl fromClauseAccess,
SqlAliasBaseManager sqlAliasBaseManager,
Consumer<SqlSelection> sqlSelectionConsumer,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory;
this.fromClauseAccess = fromClauseAccess; 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 @Override
public SqlAstCreationContext getCreationContext() { public SqlAstCreationContext getCreationContext() {
return sessionFactory; return sessionFactory;
} }
@Override @Override
public SqlAstProcessingStateImpl getCurrentProcessingState() { public SqlAstCreationStateImpl getCurrentProcessingState() {
return processingState; return this;
} }
@Override @Override
public SqlAstProcessingStateImpl getSqlExpressionResolver() { public SqlAstCreationStateImpl getSqlExpressionResolver() {
return processingState; return this;
} }
@Override @Override
@ -53,13 +92,31 @@ public class SqlAstCreationStateImpl implements SqlAstCreationState {
@Override @Override
public SqlAliasBaseGenerator getSqlAliasBaseGenerator() { public SqlAliasBaseGenerator getSqlAliasBaseGenerator() {
return stem -> { return sqlAliasBaseManager;
throw new UnsupportedOperationException();
};
} }
@Override @Override
public LockMode determineLockMode(String identificationVariable) { 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; return null;
} }
} }

View File

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

View File

@ -7,19 +7,16 @@
package org.hibernate.query.results.complete; package org.hibernate.query.results.complete;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl; import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FromClauseAccessImpl; import org.hibernate.query.results.MissingSqlSelectionException;
import org.hibernate.query.results.SqlAstCreationStateImpl; import org.hibernate.query.results.PositionalSelectionsNotAllowedException;
import org.hibernate.query.results.SqlAstProcessingStateImpl;
import org.hibernate.query.results.SqlSelectionImpl; import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy; 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.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
@ -34,13 +31,23 @@ import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnRefere
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder { public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder, ModelPartReferenceBasic {
private final NavigablePath navigablePath;
private final BasicValuedModelPart referencedModelPart; 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.referencedModelPart = referencedModelPart;
this.columnName = columnName; this.selectionAlias = selectionAlias;
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
} }
@Override @Override
@ -54,49 +61,48 @@ public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder {
NavigablePath fetchPath, NavigablePath fetchPath,
JdbcValuesMetadata jdbcResultsMetadata, JdbcValuesMetadata jdbcResultsMetadata,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver, BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) { DomainResultCreationState domainResultCreationState) {
final DomainResultCreationStateImpl domainResultCreationStateImpl = impl( domainResultCreationState ); final DomainResultCreationStateImpl creationState = impl( domainResultCreationState );
final SqlAstCreationStateImpl sqlAstCreationState = domainResultCreationStateImpl.getSqlAstCreationState();
final FromClauseAccessImpl fromClauseAccess = domainResultCreationStateImpl.getFromClauseAccess();
final SqlAstProcessingStateImpl sqlAstProcessingState = sqlAstCreationState.getCurrentProcessingState();
final String mappedTable = referencedModelPart.getContainingTableExpression(); final String mappedTable = referencedModelPart.getContainingTableExpression();
final String mappedColumn = referencedModelPart.getMappedColumnExpression(); 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 TableReference tableReference = tableGroup.getTableReference( mappedTable );
final String selectedAlias; final String selectedAlias;
final int jdbcPosition; final int jdbcPosition;
if ( columnName == null ) { if ( selectionAlias != null ) {
jdbcPosition = sqlAstProcessingState.getNumberOfProcessedSelections(); try {
selectedAlias = jdbcResultsMetadata.resolveColumnName( jdbcPosition ); 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 { else {
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnName ); if ( ! creationState.arePositionalSelectionsAllowed() ) {
selectedAlias = columnName; throw new PositionalSelectionsNotAllowedException(
"Positional SQL selection resolution not allowed"
);
}
jdbcPosition = creationState.getNumberOfProcessedSelections();
selectedAlias = jdbcResultsMetadata.resolveColumnName( jdbcPosition );
} }
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition ); final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
// we just care about the registration here. The ModelPart will find it later // we just care about the registration here. The ModelPart will find it later
creationState.resolveSqlExpression(
sqlAstProcessingState.resolveSqlExpression(
createColumnReferenceKey( tableReference, mappedColumn ), createColumnReferenceKey( tableReference, mappedColumn ),
processingState -> new SqlSelectionImpl( valuesArrayPosition, referencedModelPart ) 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( return referencedModelPart.generateFetch(
parent, 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; package org.hibernate.query.results.complete;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.BasicValuedMapping; import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.query.internal.ResultSetMappingResolutionContext; import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.internal.ScalarResultMappingMemento;
import org.hibernate.query.results.ResultsHelper; import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.query.results.SqlSelectionImpl; 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.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult; import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata; 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.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.query.results.ResultsHelper.impl;
/** /**
* ResultBuilder for scalar results defined via:<ul> * ResultBuilder for scalar results defined via:<ul>
* <li>JPA {@link javax.persistence.ColumnResult}</li> * <li>JPA {@link javax.persistence.ColumnResult}</li>
@ -37,15 +35,16 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
private final String explicitColumnName; private final String explicitColumnName;
private final BasicType<?> explicitType; private final BasicValuedMapping explicitType;
private final JavaTypeDescriptor<?> explicitJavaTypeDescriptor; private final JavaTypeDescriptor<?> explicitJavaTypeDescriptor;
public CompleteResultBuilderBasicValuedStandard( public CompleteResultBuilderBasicValuedStandard(
ScalarResultMappingMemento memento, String explicitColumnName,
ResultSetMappingResolutionContext context) { BasicValuedMapping explicitType,
this.explicitColumnName = memento.getExplicitColumnName(); JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
this.explicitType = memento.getExplicitType(); this.explicitColumnName = explicitColumnName;
this.explicitJavaTypeDescriptor = memento.getExplicitJavaTypeDescriptor(); this.explicitType = explicitType;
this.explicitJavaTypeDescriptor = explicitJavaTypeDescriptor;
} }
@Override @Override
@ -53,11 +52,9 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
JdbcValuesMetadata jdbcResultsMetadata, JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition, int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver, BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) { DomainResultCreationState domainResultCreationState) {
final SessionFactoryImplementor sessionFactory = domainResultCreationState.getSqlAstCreationState() final DomainResultCreationStateImpl creationStateImpl = impl( domainResultCreationState );
.getCreationContext() final SessionFactoryImplementor sessionFactory = creationStateImpl.getSessionFactory();
.getSessionFactory();
final int jdbcPosition; final int jdbcPosition;
final String columnName; final String columnName;
@ -73,7 +70,7 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition ); final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
final BasicType<?> basicType; final BasicValuedMapping basicType;
if ( explicitType != null ) { if ( explicitType != null ) {
basicType = explicitType; basicType = explicitType;
@ -94,10 +91,16 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
basicType = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor ); basicType = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
} }
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType ); creationStateImpl.resolveSqlSelection(
sqlSelectionConsumer.accept( sqlSelection ); 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 * @author Steve Ebersole
*/ */
public interface CompleteResultBuilderEntityValued public interface CompleteResultBuilderEntityValued
extends CompleteResultBuilder, ModelPartReference, ResultBuilderEntityValued { extends CompleteResultBuilder, ModelPartReferenceEntity, ResultBuilderEntityValued {
@Override @Override
EntityMappingType getReferencedPart(); EntityMappingType getReferencedPart();
} }

View File

@ -9,13 +9,11 @@ package org.hibernate.query.results.complete;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.query.DynamicInstantiationNature; import org.hibernate.query.DynamicInstantiationNature;
import org.hibernate.query.results.ResultBuilderInstantiationValued; import org.hibernate.query.results.ResultBuilderInstantiationValued;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy; import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.query.results.ResultBuilder; 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.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.instantiation.internal.ArgumentDomainResult; import org.hibernate.sql.results.graph.instantiation.internal.ArgumentDomainResult;
@ -46,19 +44,17 @@ public class CompleteResultBuilderInstantiation
JdbcValuesMetadata jdbcResultsMetadata, JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition, int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver, BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) { DomainResultCreationState domainResultCreationState) {
final List<ArgumentDomainResult<?>> argumentDomainResults = new ArrayList<>( argumentResultBuilders.size() ); final List<ArgumentDomainResult<?>> argumentDomainResults = new ArrayList<>( argumentResultBuilders.size() );
for ( int i = 0; i < argumentResultBuilders.size(); i++ ) { for ( int i = 0; i < argumentResultBuilders.size(); i++ ) {
final ResultBuilder argumentResultBuilder = argumentResultBuilders.get( i ); final ResultBuilder argumentResultBuilder = argumentResultBuilders.get( i );
final ArgumentDomainResult<Object> argumentDomainResult = new ArgumentDomainResult<>( @SuppressWarnings({"unchecked", "rawtypes"}) final ArgumentDomainResult<?> argumentDomainResult = new ArgumentDomainResult(
argumentResultBuilder.buildResult( argumentResultBuilder.buildResult(
jdbcResultsMetadata, jdbcResultsMetadata,
i, i,
legacyFetchResolver, legacyFetchResolver,
sqlSelectionConsumer,
domainResultCreationState domainResultCreationState
) )
); );
@ -66,7 +62,7 @@ public class CompleteResultBuilderInstantiation
argumentDomainResults.add( argumentDomainResult ); argumentDomainResults.add( argumentDomainResult );
} }
return new DynamicInstantiationResultImpl( return new DynamicInstantiationResultImpl<>(
null, null,
DynamicInstantiationNature.CLASS, DynamicInstantiationNature.CLASS,
javaTypeDescriptor, 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; package org.hibernate.query.results.complete;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.FetchBuilder; import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.ResultBuilder; import org.hibernate.query.results.ResultBuilder;
@ -17,10 +18,10 @@ import org.hibernate.query.results.ResultBuilder;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface ModelPartReference { public interface ModelPartReference {
NavigablePath getNavigablePath();
/** /**
* The part of the domain model that is referenced * The part of the domain model that is referenced
*/ */
ModelPart getReferencedPart(); 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.List;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.NativeQuery; import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath; 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.ResultsHelper;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
@ -64,11 +62,10 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
NavigablePath fetchPath, NavigablePath fetchPath,
JdbcValuesMetadata jdbcResultsMetadata, JdbcValuesMetadata jdbcResultsMetadata,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver, BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) { 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 // 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.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.NativeQuery; import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath; 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.ResultsHelper;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
@ -47,11 +45,10 @@ public class DynamicFetchBuilderStandard
NavigablePath fetchPath, NavigablePath fetchPath,
JdbcValuesMetadata jdbcResultsMetadata, JdbcValuesMetadata jdbcResultsMetadata,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver, BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) { 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 // 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.Locale;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.metamodel.mapping.SingularAttributeMapping; import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping; import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl; 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.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult; import org.hibernate.sql.results.graph.basic.BasicResult;
@ -59,15 +59,21 @@ public class DynamicResultBuilderAttribute implements DynamicResultBuilder {
JdbcValuesMetadata jdbcResultsMetadata, JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition, int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver, BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) { DomainResultCreationState domainResultCreationState) {
final int resultSetPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias ); final int resultSetPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = resultSetPosition - 1; final int valuesArrayPosition = resultSetPosition - 1;
// todo (6.0) : TableGroups + `attributeMapping#buldResult` // todo (6.0) : TableGroups + `attributeMapping#buldResult`
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, attributeMapping ); final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
sqlSelectionConsumer.accept( sqlSelection ); sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
columnAlias,
state -> new SqlSelectionImpl( valuesArrayPosition, attributeMapping )
),
attributeMapping.getJavaTypeDescriptor(),
domainResultCreationState.getSqlAstCreationState().getCreationContext().getSessionFactory().getTypeConfiguration()
);
return new BasicResult<>( return new BasicResult<>(
valuesArrayPosition, valuesArrayPosition,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,13 +9,11 @@ package org.hibernate.query.results.dynamic;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.query.DynamicInstantiationNature; import org.hibernate.query.DynamicInstantiationNature;
import org.hibernate.query.NativeQuery; import org.hibernate.query.NativeQuery;
import org.hibernate.query.results.Builders; import org.hibernate.query.results.Builders;
import org.hibernate.query.results.ResultBuilderInstantiationValued; 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.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.instantiation.internal.ArgumentDomainResult; import org.hibernate.sql.results.graph.instantiation.internal.ArgumentDomainResult;
@ -59,7 +57,6 @@ public class DynamicResultBuilderInstantiation<J>
JdbcValuesMetadata jdbcResultsMetadata, JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition, int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver, BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
Consumer<SqlSelection> sqlSelectionConsumer,
DomainResultCreationState domainResultCreationState) { DomainResultCreationState domainResultCreationState) {
if ( argumentResultBuilders.isEmpty() ) { if ( argumentResultBuilders.isEmpty() ) {
throw new IllegalStateException( "DynamicResultBuilderInstantiation defined no arguments" ); throw new IllegalStateException( "DynamicResultBuilderInstantiation defined no arguments" );
@ -70,12 +67,11 @@ public class DynamicResultBuilderInstantiation<J>
for ( int i = 0; i < argumentResultBuilders.size(); i++ ) { for ( int i = 0; i < argumentResultBuilders.size(); i++ ) {
final InstantiationArgument argument = argumentResultBuilders.get( i ); final InstantiationArgument argument = argumentResultBuilders.get( i );
final ArgumentDomainResult<Object> argumentDomainResult = new ArgumentDomainResult<>( final ArgumentDomainResult<?> argumentDomainResult = new ArgumentDomainResult(
argument.argumentBuilder.buildResult( argument.argumentBuilder.buildResult(
jdbcResultsMetadata, jdbcResultsMetadata,
i, i,
legacyFetchResolver, legacyFetchResolver,
sqlSelectionConsumer,
domainResultCreationState 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.Builders;
import org.hibernate.query.results.ResultBuilder; import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.ResultSetMappingImpl; 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.DynamicResultBuilderEntityStandard;
import org.hibernate.query.results.dynamic.DynamicResultBuilderInstantiation; 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.AbstractQuery;
import org.hibernate.query.spi.MutableQueryOptions; import org.hibernate.query.spi.MutableQueryOptions;
import org.hibernate.query.spi.NonSelectQueryPlan; import org.hibernate.query.spi.NonSelectQueryPlan;
@ -105,12 +105,12 @@ public class NativeQueryImpl<R>
private final List<QueryParameterImplementor<?>> occurrenceOrderedParamList; private final List<QueryParameterImplementor<?>> occurrenceOrderedParamList;
private final QueryParameterBindings parameterBindings; private final QueryParameterBindings parameterBindings;
private final ResultSetMappingImpl resultSetMapping;
private final QueryOptionsImpl queryOptions = new QueryOptionsImpl(); private final QueryOptionsImpl queryOptions = new QueryOptionsImpl();
private Set<String> querySpaces; private Set<String> querySpaces;
private ResultSetMappingImpl resultSetMapping = new ResultSetMappingImpl();
private Object collectionKey; private Object collectionKey;
private NativeQueryInterpreter nativeQueryInterpreter; private NativeQueryInterpreter nativeQueryInterpreter;
@ -125,11 +125,30 @@ public class NativeQueryImpl<R>
this.sqlString = memento.getSqlString(); this.sqlString = memento.getSqlString();
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session ); final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session );
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session ); this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters(); this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() ); 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 ); applyOptions( memento );
} }
@ -155,7 +174,7 @@ public class NativeQueryImpl<R>
NamedNativeQueryMemento memento, NamedNativeQueryMemento memento,
String resultSetMappingName, String resultSetMappingName,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
this( memento, session ); this( resultSetMappingName, memento, session );
session.getFactory() session.getFactory()
.getQueryEngine() .getQueryEngine()
@ -171,6 +190,8 @@ public class NativeQueryImpl<R>
super( session ); super( session );
this.sqlString = sqlString; this.sqlString = sqlString;
this.resultSetMapping = new ResultSetMappingImpl( resultSetMappingMemento.getName() );
resultSetMappingMemento.resolve( resultSetMapping, (s) -> {}, this ); resultSetMappingMemento.resolve( resultSetMapping, (s) -> {}, this );
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session ); final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session );
@ -231,6 +252,8 @@ public class NativeQueryImpl<R>
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session ); this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters(); this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() ); this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
this.resultSetMapping = new ResultSetMappingImpl( sqlString );
} }
@Override @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.Stack;
import org.hibernate.internal.util.collections.StandardStack; import org.hibernate.internal.util.collections.StandardStack;
import org.hibernate.loader.MultipleBagFetchException; import org.hibernate.loader.MultipleBagFetchException;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
@ -294,12 +295,16 @@ public class StandardSqmSelectTranslator
final Fetch fetch = buildFetch( fetchablePath, fetchParent, fetchable, isKeyFetchable ); final Fetch fetch = buildFetch( fetchablePath, fetchParent, fetchable, isKeyFetchable );
if ( fetch != null ) { if ( fetch != null ) {
if ( fetch.getTiming() == FetchTiming.IMMEDIATE && if ( fetch.getTiming() == FetchTiming.IMMEDIATE && fetchable instanceof PluralAttributeMapping ) {
fetchable instanceof PluralAttributeMapping && final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) fetchable;
( (PluralAttributeMapping) fetchable ).getMappedTypeDescriptor() final CollectionClassification collectionClassification = pluralAttributeMapping.getMappedTypeDescriptor()
.getCollectionSemantics() instanceof BagSemantics ) { .getCollectionSemantics()
bagRoles.add( fetchable.getNavigableRole().getNavigableName() ); .getCollectionClassification();
if ( collectionClassification == CollectionClassification.BAG ) {
bagRoles.add( fetchable.getNavigableRole().getNavigableName() );
}
} }
fetches.add( fetch ); fetches.add( fetch );
} }
} }

View File

@ -17,6 +17,13 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface DomainResultGraphNode { 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 // todo (6.0) : result variable (selection alias)? - even fetches can have alias
JavaTypeDescriptor getResultJavaTypeDescriptor(); JavaTypeDescriptor getResultJavaTypeDescriptor();

View File

@ -56,8 +56,13 @@ public interface Fetch extends DomainResultGraphNode {
*/ */
boolean hasTableGroup(); boolean hasTableGroup();
@Override
default boolean containsAnyNonScalarResults() {
return true;
}
/** /**
* Create the assembler for this fetch * 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; return resultVariable;
} }
@Override
public boolean containsAnyNonScalarResults() {
return true;
}
@Override @Override
public JavaTypeDescriptor getResultJavaTypeDescriptor() { public JavaTypeDescriptor getResultJavaTypeDescriptor() {
return loadingAttribute.getJavaTypeDescriptor(); return loadingAttribute.getJavaTypeDescriptor();

View File

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

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.sql.results.graph.embeddable.internal; package org.hibernate.sql.results.graph.embeddable.internal;
import java.util.List;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; 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.DomainResult;
import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.DomainResultGraphNode;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer;
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode; import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; 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> { public class EmbeddableResultImpl<T> extends AbstractFetchParent implements EmbeddableResultGraphNode, DomainResult<T> {
private final String resultVariable; private final String resultVariable;
private final boolean containsAnyNonScalars;
public EmbeddableResultImpl( public EmbeddableResultImpl(
NavigablePath navigablePath, NavigablePath navigablePath,
@ -56,6 +61,19 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
); );
afterInitialize( creationState ); 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 @Override
@ -63,6 +81,11 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
return resultVariable; return resultVariable;
} }
@Override
public boolean containsAnyNonScalarResults() {
return containsAnyNonScalars;
}
@Override @Override
public EmbeddableMappingType getFetchContainer() { public EmbeddableMappingType getFetchContainer() {
return (EmbeddableMappingType) super.getFetchContainer(); return (EmbeddableMappingType) super.getFetchContainer();

View File

@ -12,4 +12,8 @@ import org.hibernate.sql.results.graph.Fetch;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface EntityFetch extends EntityResultGraphNode, Fetch { 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(); NavigablePath getNavigablePath();
EntityValuedModelPart getEntityValuedModelPart(); EntityValuedModelPart getEntityValuedModelPart();
@Override
default boolean containsAnyNonScalarResults() {
return true;
}
@Override @Override
default JavaTypeDescriptor getResultJavaTypeDescriptor() { default JavaTypeDescriptor getResultJavaTypeDescriptor() {

View File

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

View File

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

View File

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

View File

@ -10,6 +10,7 @@ import java.lang.reflect.Constructor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
@ -32,13 +33,13 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
private final DynamicInstantiationNature nature; private final DynamicInstantiationNature nature;
private final JavaTypeDescriptor<R> javaTypeDescriptor; private final JavaTypeDescriptor<R> javaTypeDescriptor;
private final List<ArgumentDomainResult> argumentResults; private final List<ArgumentDomainResult<?>> argumentResults;
public DynamicInstantiationResultImpl( public DynamicInstantiationResultImpl(
String resultVariable, String resultVariable,
DynamicInstantiationNature nature, DynamicInstantiationNature nature,
JavaTypeDescriptor<R> javaTypeDescriptor, JavaTypeDescriptor<R> javaTypeDescriptor,
List<ArgumentDomainResult> argumentResults) { List<ArgumentDomainResult<?>> argumentResults) {
this.resultVariable = resultVariable; this.resultVariable = resultVariable;
this.nature = nature; this.nature = nature;
this.javaTypeDescriptor = javaTypeDescriptor; this.javaTypeDescriptor = javaTypeDescriptor;
@ -46,7 +47,7 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
} }
@Override @Override
public JavaTypeDescriptor getResultJavaTypeDescriptor() { public JavaTypeDescriptor<R> getResultJavaTypeDescriptor() {
return javaTypeDescriptor; return javaTypeDescriptor;
} }
@ -55,6 +56,19 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
return resultVariable; 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 @Override
public DomainResultAssembler<R> createResultAssembler(AssemblerCreationState creationState) { public DomainResultAssembler<R> createResultAssembler(AssemblerCreationState creationState) {
boolean areAllArgumentsAliased = true; boolean areAllArgumentsAliased = true;
@ -64,7 +78,7 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
final List<ArgumentReader<?>> argumentReaders = new ArrayList<>(); final List<ArgumentReader<?>> argumentReaders = new ArrayList<>();
if ( argumentResults != null ) { if ( argumentResults != null ) {
for ( ArgumentDomainResult argumentResult : argumentResults ) { for ( ArgumentDomainResult<?> argumentResult : argumentResults ) {
final String argumentAlias = argumentResult.getResultVariable(); final String argumentAlias = argumentResult.getResultVariable();
if ( argumentAlias == null ) { if ( argumentAlias == null ) {
areAllArgumentsAliased = false; 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" ); log.debug( "One or more arguments for List dynamic instantiation (`new list(...)`) specified an alias; ignoring" );
} }
return (DomainResultAssembler<R>) new DynamicInstantiationAssemblerListImpl( return (DomainResultAssembler<R>) new DynamicInstantiationAssemblerListImpl(
(JavaTypeDescriptor<List>) javaTypeDescriptor, (JavaTypeDescriptor<List<?>>) javaTypeDescriptor,
argumentReaders argumentReaders
); );
} }
@ -121,21 +135,21 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
); );
} }
return (DomainResultAssembler<R>) new DynamicInstantiationAssemblerMapImpl( return (DomainResultAssembler<R>) new DynamicInstantiationAssemblerMapImpl(
(JavaTypeDescriptor) javaTypeDescriptor, (JavaTypeDescriptor<Map<?,?>>) javaTypeDescriptor,
argumentReaders argumentReaders
); );
} }
else { else {
// find a constructor matching argument types // find a constructor matching argument types
constructor_loop: constructor_loop:
for ( Constructor constructor : javaTypeDescriptor.getJavaType().getDeclaredConstructors() ) { for ( Constructor<?> constructor : javaTypeDescriptor.getJavaType().getDeclaredConstructors() ) {
if ( constructor.getParameterTypes().length != argumentReaders.size() ) { if ( constructor.getParameterTypes().length != argumentReaders.size() ) {
continue; continue;
} }
for ( int i = 0; i < argumentReaders.size(); i++ ) { for ( int i = 0; i < argumentReaders.size(); i++ ) {
final ArgumentReader argumentReader = argumentReaders.get( i ); final ArgumentReader<?> argumentReader = argumentReaders.get( i );
final JavaTypeDescriptor argumentTypeDescriptor = creationState.getSqlAstCreationContext() final JavaTypeDescriptor<?> argumentTypeDescriptor = creationState.getSqlAstCreationContext()
.getDomainModel() .getDomainModel()
.getTypeConfiguration() .getTypeConfiguration()
.getJavaTypeDescriptorRegistry() .getJavaTypeDescriptorRegistry()
@ -159,6 +173,7 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
} }
constructor.setAccessible( true ); constructor.setAccessible( true );
//noinspection rawtypes
return new DynamicInstantiationAssemblerConstructorImpl( return new DynamicInstantiationAssemblerConstructorImpl(
constructor, constructor,
javaTypeDescriptor, 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; package org.hibernate.orm.test.query.named.resultmapping;
import javax.persistence.Basic;
import javax.persistence.ColumnResult; import javax.persistence.ColumnResult;
import javax.persistence.ConstructorResult; import javax.persistence.ConstructorResult;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EntityResult; import javax.persistence.EntityResult;
import javax.persistence.FetchType;
import javax.persistence.FieldResult; import javax.persistence.FieldResult;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.SqlResultSetMapping; import javax.persistence.SqlResultSetMapping;
@ -40,7 +42,7 @@ import javax.persistence.SqlResultSetMapping;
) )
) )
@SqlResultSetMapping( @SqlResultSetMapping(
name = "entity", name = "entity-id-name",
entities = @EntityResult( entities = @EntityResult(
entityClass = SimpleEntityWithNamedMappings.class, entityClass = SimpleEntityWithNamedMappings.class,
fields = { 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 { public class SimpleEntityWithNamedMappings {
@Id @Id
private Integer id; private Integer id;
private String name; private String name;
private String notes;
protected SimpleEntityWithNamedMappings() { protected SimpleEntityWithNamedMappings() {
} }
public SimpleEntityWithNamedMappings(Integer id, String name) { public SimpleEntityWithNamedMappings(Integer id, String name) {
this( id, name, null );
}
public SimpleEntityWithNamedMappings(Integer id, String name, String notes) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.notes = notes;
} }
public Integer getId() { public Integer getId() {
@ -79,6 +108,15 @@ public class SimpleEntityWithNamedMappings {
this.name = name; this.name = name;
} }
@Basic( fetch = FetchType.LAZY )
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public static class DropDownDto { public static class DropDownDto {
private final Integer id; private final Integer id;
private final String text; private final String text;

View File

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

View File

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