mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-03-04 16:59:29 +00:00
ResultSet mapping
Split handling of result / fetch builders created from: complete:: Cases where we completely know the builder graph up-front dynamic:: Cases where the builder graph is generated at runtime
This commit is contained in:
parent
283c3fefb5
commit
b1e8f64bda
@ -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.annotations;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NoAttributeConverter<O,R> implements AttributeConverter<O,R> {
|
||||
@Override
|
||||
public R convertToDatabaseColumn(Object attribute) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public O convertToEntityAttribute(Object dbData) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedProcedureCallDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDescriptor;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
@ -147,12 +147,12 @@ public interface Metadata extends Mapping {
|
||||
*
|
||||
* @return The named result set mapping metadata, or {@code null} if none found.
|
||||
*/
|
||||
NamedResultSetMappingDefinition getResultSetMapping(String name);
|
||||
NamedResultSetMappingDescriptor getResultSetMapping(String name);
|
||||
|
||||
/**
|
||||
* Visit all named SQL result set mapping definitions
|
||||
*/
|
||||
void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDefinition> definitionConsumer);
|
||||
void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDescriptor> definitionConsumer);
|
||||
|
||||
/**
|
||||
* Retrieve a type definition by name.
|
||||
|
@ -61,7 +61,7 @@
|
||||
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedProcedureCallDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDescriptor;
|
||||
import org.hibernate.boot.spi.NaturalIdUniqueKeyBinder;
|
||||
import org.hibernate.cfg.AnnotatedClassType;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
@ -142,7 +142,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
||||
private final Map<String, NamedHqlQueryDefinition> namedQueryMap = new HashMap<>();
|
||||
private final Map<String, NamedNativeQueryDefinition> namedNativeQueryMap = new HashMap<>();
|
||||
private final Map<String, NamedProcedureCallDefinition> namedProcedureCallMap = new HashMap<>();
|
||||
private final Map<String, NamedResultSetMappingDefinition> sqlResultSetMappingMap = new HashMap<>();
|
||||
private final Map<String, NamedResultSetMappingDescriptor> sqlResultSetMappingMap = new HashMap<>();
|
||||
|
||||
private final Map<String, NamedEntityGraphDefinition> namedEntityGraphMap = new HashMap<>();
|
||||
private final Map<String, FetchProfile> fetchProfileMap = new HashMap<>();
|
||||
@ -648,17 +648,17 @@ public void addDefaultNamedProcedureCall(NamedProcedureCallDefinitionImpl defini
|
||||
// result-set mapping handling
|
||||
|
||||
@Override
|
||||
public NamedResultSetMappingDefinition getResultSetMapping(String name) {
|
||||
public NamedResultSetMappingDescriptor getResultSetMapping(String name) {
|
||||
return sqlResultSetMappingMap.get( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDefinition> definitionConsumer) {
|
||||
public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDescriptor> definitionConsumer) {
|
||||
sqlResultSetMappingMap.values().forEach( definitionConsumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResultSetMapping(NamedResultSetMappingDefinition resultSetMappingDescriptor) {
|
||||
public void addResultSetMapping(NamedResultSetMappingDescriptor resultSetMappingDescriptor) {
|
||||
if ( resultSetMappingDescriptor == null ) {
|
||||
throw new IllegalArgumentException( "Result-set mapping was null" );
|
||||
}
|
||||
@ -675,8 +675,8 @@ public void addResultSetMapping(NamedResultSetMappingDefinition resultSetMapping
|
||||
applyResultSetMapping( resultSetMappingDescriptor );
|
||||
}
|
||||
|
||||
public void applyResultSetMapping(NamedResultSetMappingDefinition resultSetMappingDescriptor) {
|
||||
final NamedResultSetMappingDefinition old = sqlResultSetMappingMap.put(
|
||||
public void applyResultSetMapping(NamedResultSetMappingDescriptor resultSetMappingDescriptor) {
|
||||
final NamedResultSetMappingDescriptor old = sqlResultSetMappingMap.put(
|
||||
resultSetMappingDescriptor.getRegistrationName(),
|
||||
resultSetMappingDescriptor
|
||||
);
|
||||
@ -689,7 +689,7 @@ public void applyResultSetMapping(NamedResultSetMappingDefinition resultSetMappi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDefaultResultSetMapping(NamedResultSetMappingDefinition definition) {
|
||||
public void addDefaultResultSetMapping(NamedResultSetMappingDescriptor definition) {
|
||||
final String name = definition.getRegistrationName();
|
||||
if ( !defaultSqlResultSetMappingNames.contains( name ) ) {
|
||||
sqlResultSetMappingMap.remove( name );
|
||||
|
@ -33,7 +33,7 @@
|
||||
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedProcedureCallDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDescriptor;
|
||||
import org.hibernate.boot.spi.SessionFactoryBuilderFactory;
|
||||
import org.hibernate.boot.spi.SessionFactoryBuilderImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryBuilderService;
|
||||
@ -89,7 +89,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||
private final Map<String, NamedHqlQueryDefinition> namedQueryMap;
|
||||
private final Map<String, NamedNativeQueryDefinition> namedNativeQueryMap;
|
||||
private final Map<String, NamedProcedureCallDefinition> namedProcedureCallMap;
|
||||
private final Map<String, NamedResultSetMappingDefinition> sqlResultSetMappingMap;
|
||||
private final Map<String, NamedResultSetMappingDescriptor> sqlResultSetMappingMap;
|
||||
private final Map<String, NamedEntityGraphDefinition> namedEntityGraphMap;
|
||||
private final Map<String, SqmFunctionDescriptor> sqlFunctionMap;
|
||||
private final Database database;
|
||||
@ -110,7 +110,7 @@ public MetadataImpl(
|
||||
Map<String, NamedHqlQueryDefinition> namedQueryMap,
|
||||
Map<String, NamedNativeQueryDefinition> namedNativeQueryMap,
|
||||
Map<String, NamedProcedureCallDefinition> namedProcedureCallMap,
|
||||
Map<String, NamedResultSetMappingDefinition> sqlResultSetMappingMap,
|
||||
Map<String, NamedResultSetMappingDescriptor> sqlResultSetMappingMap,
|
||||
Map<String, NamedEntityGraphDefinition> namedEntityGraphMap,
|
||||
Map<String, SqmFunctionDescriptor> sqlFunctionMap,
|
||||
Database database,
|
||||
@ -253,12 +253,12 @@ public void visitNamedProcedureCallDefinition(Consumer<NamedProcedureCallDefinit
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedResultSetMappingDefinition getResultSetMapping(String name) {
|
||||
public NamedResultSetMappingDescriptor getResultSetMapping(String name) {
|
||||
return sqlResultSetMappingMap.get( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDefinition> definitionConsumer) {
|
||||
public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDescriptor> definitionConsumer) {
|
||||
sqlResultSetMappingMap.values().forEach( definitionConsumer );
|
||||
}
|
||||
|
||||
@ -350,14 +350,6 @@ private Map<String, NamedCallableQueryMemento> buildProcedureCallMementos(Sessio
|
||||
return map;
|
||||
}
|
||||
|
||||
private Map<String, NamedResultSetMappingMemento> buildResultSetMappingMementos(SessionFactoryImplementor sessionFactory) {
|
||||
final HashMap<String, NamedResultSetMappingMemento> map = new HashMap<>();
|
||||
if ( sqlResultSetMappingMap != null ) {
|
||||
sqlResultSetMappingMap.forEach( (key, value) -> map.put( key, value.resolve( sessionFactory ) ) );
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws MappingException {
|
||||
for ( PersistentClass entityBinding : this.getEntityBindings() ) {
|
||||
|
@ -28,7 +28,7 @@
|
||||
import org.hibernate.boot.model.source.spi.ToolingHintContext;
|
||||
import org.hibernate.boot.spi.BootstrapContext;
|
||||
import org.hibernate.boot.spi.ClassLoaderAccess;
|
||||
import org.hibernate.boot.query.HbmResultSetMappingDefinition;
|
||||
import org.hibernate.boot.query.HbmResultSetMappingDescriptor;
|
||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.boot.spi.MappingDefaults;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
@ -244,7 +244,7 @@ public void postProcessEntityHierarchies() {
|
||||
@Override
|
||||
public void processResultSetMappings() {
|
||||
for ( ResultSetMappingBindingDefinition resultSetMappingBinding : documentRoot.getResultset() ) {
|
||||
final HbmResultSetMappingDefinition binding = ResultSetMappingBinder.bind( resultSetMappingBinding, this );
|
||||
final HbmResultSetMappingDescriptor binding = ResultSetMappingBinder.bind( resultSetMappingBinding, this );
|
||||
getMetadataCollector().addResultSetMapping( binding );
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType;
|
||||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmQueryParamType;
|
||||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmSynchronizeType;
|
||||
import org.hibernate.boot.query.HbmResultSetMappingDefinition;
|
||||
import org.hibernate.boot.query.HbmResultSetMappingDefinitionBuilder;
|
||||
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedNativeQueryDefinitionBuilder;
|
||||
|
@ -24,7 +24,7 @@
|
||||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType;
|
||||
import org.hibernate.boot.jaxb.hbm.spi.NativeQueryNonScalarRootReturn;
|
||||
import org.hibernate.boot.jaxb.hbm.spi.ResultSetMappingBindingDefinition;
|
||||
import org.hibernate.boot.query.HbmResultSetMappingDefinition;
|
||||
import org.hibernate.boot.query.HbmResultSetMappingDescriptor;
|
||||
import org.hibernate.boot.query.HbmResultSetMappingDefinitionBuilder;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryCollectionReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryJoinReturn;
|
||||
@ -56,7 +56,7 @@ public abstract class ResultSetMappingBinder {
|
||||
*
|
||||
* @return The ResultSet mapping descriptor
|
||||
*/
|
||||
public static HbmResultSetMappingDefinition bind(
|
||||
public static HbmResultSetMappingDescriptor bind(
|
||||
ResultSetMappingBindingDefinition resultSetMappingSource,
|
||||
HbmLocalMetadataBuildingContext context) {
|
||||
if ( resultSetMappingSource.getName() == null ) {
|
||||
@ -80,7 +80,7 @@ else if ( valueMappingSource instanceof JaxbHbmNativeQueryScalarReturnType ) {
|
||||
}
|
||||
}
|
||||
|
||||
final HbmResultSetMappingDefinition mappingDefinition = builder.build( context );
|
||||
final HbmResultSetMappingDescriptor mappingDefinition = builder.build( context );
|
||||
context.getMetadataCollector().addResultSetMapping( mappingDefinition );
|
||||
return mappingDefinition;
|
||||
}
|
||||
|
@ -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.boot.query;
|
||||
|
||||
import org.hibernate.query.internal.FetchMappingMemento;
|
||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||
|
||||
/**
|
||||
* Describes the mapping for a fetch as part of a {@link NamedResultSetMappingDescriptor}
|
||||
*/
|
||||
public interface FetchDescriptor {
|
||||
/**
|
||||
* Resolve the descriptor into a memento capable of being stored in the
|
||||
* {@link org.hibernate.query.named.NamedQueryRepository}
|
||||
*/
|
||||
FetchMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext);
|
||||
}
|
@ -22,10 +22,10 @@
|
||||
public class HbmResultSetMappingDefinitionBuilder {
|
||||
private final String registrationName;
|
||||
|
||||
private NamedResultSetMappingDefinition.ResultMapping rootEntityReturn;
|
||||
private NamedResultSetMappingDefinition.ResultMapping rootCollectionReturn;
|
||||
private List<NamedResultSetMappingDefinition.ResultMapping> joinReturns;
|
||||
private List<HbmResultSetMappingDefinition.ScalarMappingDefinition> rootScalarReturns;
|
||||
private ResultDescriptor rootEntityReturn;
|
||||
private ResultDescriptor rootCollectionReturn;
|
||||
private List<ResultDescriptor> joinReturns;
|
||||
private List<HbmResultSetMappingDescriptor.ScalarDescriptor> rootScalarReturns;
|
||||
|
||||
public HbmResultSetMappingDefinitionBuilder(String queryRegistrationName) {
|
||||
this.registrationName = queryRegistrationName;
|
||||
@ -37,7 +37,7 @@ public String getRegistrationName() {
|
||||
|
||||
public HbmResultSetMappingDefinitionBuilder addReturn(JaxbHbmNativeQueryScalarReturnType returnMapping) {
|
||||
rootScalarReturns.add(
|
||||
new HbmResultSetMappingDefinition.ScalarMappingDefinition(
|
||||
new HbmResultSetMappingDescriptor.ScalarDescriptor(
|
||||
returnMapping.getColumn(),
|
||||
returnMapping.getType()
|
||||
)
|
||||
@ -61,7 +61,7 @@ public boolean hasAnyReturns() {
|
||||
return rootEntityReturn != null || rootCollectionReturn != null || rootScalarReturns != null;
|
||||
}
|
||||
|
||||
public HbmResultSetMappingDefinition build(HbmLocalMetadataBuildingContext context) {
|
||||
public HbmResultSetMappingDescriptor build(HbmLocalMetadataBuildingContext context) {
|
||||
if ( rootCollectionReturn != null
|
||||
&& ( rootEntityReturn != null || rootScalarReturns != null ) ) {
|
||||
throw new MappingException(
|
||||
@ -79,7 +79,7 @@ public HbmResultSetMappingDefinition build(HbmLocalMetadataBuildingContext conte
|
||||
}
|
||||
}
|
||||
|
||||
return new HbmResultSetMappingDefinition(
|
||||
return new HbmResultSetMappingDescriptor(
|
||||
registrationName,
|
||||
rootEntityReturn,
|
||||
rootCollectionReturn,
|
||||
|
@ -7,14 +7,14 @@
|
||||
package org.hibernate.boot.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||
import org.hibernate.query.internal.ScalarResultMappingMemento;
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.results.Builders;
|
||||
import org.hibernate.query.results.ScalarResultBuilder;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
||||
/**
|
||||
@ -27,22 +27,22 @@
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class HbmResultSetMappingDefinition implements NamedResultSetMappingDefinition {
|
||||
public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescriptor {
|
||||
// todo (6.0) : see note on org.hibernate.boot.query.SqlResultSetMappingDefinition
|
||||
|
||||
private final String registrationName;
|
||||
|
||||
private final ResultMapping rootEntityReturn;
|
||||
private final ResultMapping rootCollectionReturn;
|
||||
private final List<ResultMapping> joinReturns;
|
||||
private final List<ScalarMappingDefinition> scalarResultMappings;
|
||||
private final ResultDescriptor rootEntityReturn;
|
||||
private final ResultDescriptor rootCollectionReturn;
|
||||
private final List<ResultDescriptor> joinReturns;
|
||||
private final List<ScalarDescriptor> scalarResultMappings;
|
||||
|
||||
public HbmResultSetMappingDefinition(
|
||||
public HbmResultSetMappingDescriptor(
|
||||
String registrationName,
|
||||
ResultMapping rootEntityReturn,
|
||||
ResultMapping rootCollectionReturn,
|
||||
List<ResultMapping> joinReturns,
|
||||
List<ScalarMappingDefinition> scalarResultMappings) {
|
||||
ResultDescriptor rootEntityReturn,
|
||||
ResultDescriptor rootCollectionReturn,
|
||||
List<ResultDescriptor> joinReturns,
|
||||
List<ScalarDescriptor> scalarResultMappings) {
|
||||
this.registrationName = registrationName;
|
||||
|
||||
this.rootEntityReturn = rootEntityReturn;
|
||||
@ -57,16 +57,16 @@ public String getRegistrationName() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedResultSetMappingMemento resolve(SessionFactoryImplementor factory) {
|
||||
final List<ScalarResultBuilder> scalarResultBuilders;
|
||||
public NamedResultSetMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
|
||||
final List<ScalarResultMappingMemento> scalarResultMementos;
|
||||
if ( scalarResultMappings == null || scalarResultMappings.isEmpty() ) {
|
||||
scalarResultBuilders = null;
|
||||
scalarResultMementos = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
scalarResultBuilders = new ArrayList<>( scalarResultMappings.size() );
|
||||
scalarResultMementos = new ArrayList<>( scalarResultMappings.size() );
|
||||
scalarResultMappings.forEach(
|
||||
resultMapping -> {
|
||||
scalarResultBuilders.add( resultMapping.resolve( factory ) );
|
||||
scalarResultMementos.add( resultMapping.resolve( resolutionContext ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -81,12 +81,12 @@ public NamedResultSetMappingMemento resolve(SessionFactoryImplementor factory) {
|
||||
/**
|
||||
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryReturnType
|
||||
*/
|
||||
public interface RootEntityMappingDefinition extends ResultMapping {
|
||||
public interface RootEntityDescriptor extends ResultDescriptor {
|
||||
String getEntityName();
|
||||
|
||||
String getSqlAlias();
|
||||
|
||||
List<HbmPropertyMappingDefinition> getProperties();
|
||||
List<HbmPropertyDescriptor> getProperties();
|
||||
|
||||
String getDiscriminatorColumnName();
|
||||
|
||||
@ -96,7 +96,7 @@ public interface RootEntityMappingDefinition extends ResultMapping {
|
||||
/**
|
||||
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryPropertyReturnType
|
||||
*/
|
||||
public interface HbmPropertyMappingDefinition extends ResultMapping {
|
||||
public interface HbmPropertyDescriptor extends ResultDescriptor {
|
||||
String getPropertyPath();
|
||||
List<String> getColumnNames();
|
||||
}
|
||||
@ -104,12 +104,12 @@ public interface HbmPropertyMappingDefinition extends ResultMapping {
|
||||
/**
|
||||
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryJoinReturnType
|
||||
*/
|
||||
public interface JoinMappingDefinition extends ResultMapping {
|
||||
public interface JoinDescriptor extends ResultDescriptor {
|
||||
String getJoinedPropertyPath();
|
||||
|
||||
String getSqlAlias();
|
||||
|
||||
List<HbmPropertyMappingDefinition> getProperties();
|
||||
List<HbmPropertyDescriptor> getProperties();
|
||||
|
||||
LockMode getLockMode();
|
||||
}
|
||||
@ -117,12 +117,12 @@ public interface JoinMappingDefinition extends ResultMapping {
|
||||
/**
|
||||
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryCollectionLoadReturnType
|
||||
*/
|
||||
public interface RootCollectionMappingDefinition extends ResultMapping {
|
||||
public interface RootCollectionDescriptor extends ResultDescriptor {
|
||||
String getCollectionRole();
|
||||
|
||||
String getSqlAlias();
|
||||
|
||||
List<HbmPropertyMappingDefinition> getProperties();
|
||||
List<HbmPropertyDescriptor> getProperties();
|
||||
|
||||
LockMode getLockMode();
|
||||
}
|
||||
@ -130,11 +130,11 @@ public interface RootCollectionMappingDefinition extends ResultMapping {
|
||||
/**
|
||||
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType
|
||||
*/
|
||||
public static class ScalarMappingDefinition implements ResultMapping {
|
||||
public static class ScalarDescriptor implements ResultDescriptor {
|
||||
private final String columnName;
|
||||
private final String hibernateTypeName;
|
||||
|
||||
public ScalarMappingDefinition(String columnName, String hibernateTypeName) {
|
||||
public ScalarDescriptor(String columnName, String hibernateTypeName) {
|
||||
this.columnName = columnName;
|
||||
this.hibernateTypeName = hibernateTypeName;
|
||||
}
|
||||
@ -148,9 +148,10 @@ public String getHibernateTypeName() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarResultBuilder resolve(SessionFactoryImplementor factory) {
|
||||
public ScalarResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
|
||||
if ( hibernateTypeName != null ) {
|
||||
final BasicType<?> namedType = factory.getTypeConfiguration()
|
||||
final BasicType<?> namedType = resolutionContext.getSessionFactory()
|
||||
.getTypeConfiguration()
|
||||
.getBasicTypeRegistry()
|
||||
.getRegisteredType( hibernateTypeName );
|
||||
|
||||
@ -158,12 +159,12 @@ public ScalarResultBuilder resolve(SessionFactoryImplementor factory) {
|
||||
throw new IllegalArgumentException( "Could not resolve named type : " + hibernateTypeName );
|
||||
}
|
||||
|
||||
return Builders.scalar( columnName );
|
||||
return new ScalarResultMappingMemento( columnName, namedType, resolutionContext );
|
||||
}
|
||||
|
||||
// todo (6.0) : column name may be optional in HBM - double check
|
||||
|
||||
return Builders.scalar( columnName );
|
||||
return new ScalarResultMappingMemento( columnName, null, resolutionContext );
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,10 @@
|
||||
*/
|
||||
package org.hibernate.boot.query;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.internal.FetchMappingMemento;
|
||||
import org.hibernate.query.internal.ResultMappingMemento;
|
||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
|
||||
/**
|
||||
* Models the "boot view" of a ResultSet mapping used in the mapping
|
||||
@ -20,21 +21,15 @@
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface NamedResultSetMappingDefinition {
|
||||
public interface NamedResultSetMappingDescriptor {
|
||||
/**
|
||||
* The name under which the result-set-mapping is to be registered
|
||||
*/
|
||||
String getRegistrationName();
|
||||
|
||||
/**
|
||||
* Contract for the individual result mappings
|
||||
*/
|
||||
interface ResultMapping {
|
||||
ResultBuilder resolve(SessionFactoryImplementor factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the named runtime memento instance
|
||||
* @param resolutionContext
|
||||
*/
|
||||
NamedResultSetMappingMemento resolve(SessionFactoryImplementor factory);
|
||||
NamedResultSetMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.boot.query;
|
||||
|
||||
import org.hibernate.query.internal.ResultMappingMemento;
|
||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||
|
||||
/**
|
||||
* Describes the mapping for a result as part of a {@link NamedResultSetMappingDescriptor}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ResultDescriptor {
|
||||
/**
|
||||
* Resolve the descriptor into a memento capable of being stored in the
|
||||
* {@link org.hibernate.query.named.NamedQueryRepository}
|
||||
*/
|
||||
ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext);
|
||||
}
|
@ -1,261 +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.boot.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.persistence.ColumnResult;
|
||||
import javax.persistence.ConstructorResult;
|
||||
import javax.persistence.EntityResult;
|
||||
import javax.persistence.SqlResultSetMapping;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.boot.BootLogging;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl;
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.results.EntityResultBuilder;
|
||||
import org.hibernate.query.results.InstantiationResultBuilder;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ScalarResultBuilder;
|
||||
import org.hibernate.query.results.StandardInstantiationResultBuilder;
|
||||
import org.hibernate.query.results.StandardScalarResultBuilder;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqlResultSetMappingDefinition implements NamedResultSetMappingDefinition {
|
||||
|
||||
// todo (6.0) : we can probably reuse the NamedResultSetMappingDefinition
|
||||
// implementation between HBM and annotation handling. We'd
|
||||
// just need different "builders" for each source and handle the
|
||||
// variances in those builders. But once we have a
|
||||
// NamedResultSetMappingDefinition and all of its sub-parts,
|
||||
// resolving to a memento is the same
|
||||
// -
|
||||
// additionally, consider having the sub-parts (the return
|
||||
// representations) be what is used and handed to the
|
||||
// NamedResultSetMappingMemento directly. They simply need
|
||||
// to be capable of resolving themselves into ResultBuilders
|
||||
// (`org.hibernate.query.results.ResultBuilder`) as part of the
|
||||
// memento for its resolution
|
||||
|
||||
public static SqlResultSetMappingDefinition from(
|
||||
SqlResultSetMapping mappingAnnotation,
|
||||
MetadataBuildingContext context) {
|
||||
|
||||
final List<EntityResultMapping> entityResultMappings;
|
||||
final List<ConstructorResultMapping> constructorResultMappings;
|
||||
final List<JpaColumnResultMapping> columnResultMappings;
|
||||
|
||||
final EntityResult[] entityResults = mappingAnnotation.entities();
|
||||
if ( entityResults.length > 0 ) {
|
||||
entityResultMappings = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
entityResultMappings = new ArrayList<>( entityResults.length );
|
||||
for ( int i = 0; i < entityResults.length; i++ ) {
|
||||
final EntityResult entityResult = entityResults[i];
|
||||
entityResultMappings.add( EntityResultMapping.from( entityResult, context ) );
|
||||
}
|
||||
}
|
||||
|
||||
final ConstructorResult[] constructorResults = mappingAnnotation.classes();
|
||||
if ( constructorResults.length == 0 ) {
|
||||
constructorResultMappings = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
constructorResultMappings = new ArrayList<>( constructorResults.length );
|
||||
for ( int i = 0; i < constructorResults.length; i++ ) {
|
||||
final ConstructorResult constructorResult = constructorResults[i];
|
||||
constructorResultMappings.add( ConstructorResultMapping.from( constructorResult, context ) );
|
||||
}
|
||||
}
|
||||
|
||||
final ColumnResult[] columnResults = mappingAnnotation.columns();
|
||||
if ( columnResults.length == 0 ) {
|
||||
columnResultMappings = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
columnResultMappings = new ArrayList<>( columnResults.length );
|
||||
for ( int i = 0; i < columnResults.length; i++ ) {
|
||||
final ColumnResult columnResult = columnResults[i];
|
||||
columnResultMappings.add( JpaColumnResultMapping.from( columnResult, context ) );
|
||||
}
|
||||
}
|
||||
|
||||
return new SqlResultSetMappingDefinition(
|
||||
mappingAnnotation.name(),
|
||||
entityResultMappings,
|
||||
constructorResultMappings,
|
||||
columnResultMappings,
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
private final String mappingName;
|
||||
|
||||
private final List<EntityResultMapping> entityResultMappings;
|
||||
private final List<ConstructorResultMapping> constructorResultMappings;
|
||||
private final List<JpaColumnResultMapping> columnResultMappings;
|
||||
|
||||
private SqlResultSetMappingDefinition(
|
||||
String mappingName,
|
||||
List<EntityResultMapping> entityResultMappings,
|
||||
List<ConstructorResultMapping> constructorResultMappings,
|
||||
List<JpaColumnResultMapping> columnResultMappings,
|
||||
MetadataBuildingContext context) {
|
||||
this.mappingName = mappingName;
|
||||
this.entityResultMappings = entityResultMappings;
|
||||
this.constructorResultMappings = constructorResultMappings;
|
||||
this.columnResultMappings = columnResultMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRegistrationName() {
|
||||
return mappingName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedResultSetMappingMemento resolve(SessionFactoryImplementor factory) {
|
||||
final List<EntityResultBuilder> entityResultBuilders = new ArrayList<>();
|
||||
for ( int i = 0; i < entityResultMappings.size(); i++ ) {
|
||||
final EntityResultMapping resultMapping = entityResultMappings.get( i );
|
||||
entityResultBuilders.add( resultMapping.resolve( factory ) );
|
||||
}
|
||||
|
||||
final List<InstantiationResultBuilder> instantiationResultBuilders = new ArrayList<>();
|
||||
for ( int i = 0; i < constructorResultMappings.size(); i++ ) {
|
||||
final ConstructorResultMapping resultMapping = constructorResultMappings.get( i );
|
||||
instantiationResultBuilders.add( resultMapping.resolve( factory ) );
|
||||
}
|
||||
|
||||
final List<ScalarResultBuilder> scalarResultBuilders = new ArrayList<>();
|
||||
for ( int i = 0; i < columnResultMappings.size(); i++ ) {
|
||||
final JpaColumnResultMapping resultMapping = columnResultMappings.get( i );
|
||||
scalarResultBuilders.add( resultMapping.resolve( factory ) );
|
||||
}
|
||||
|
||||
return new NamedResultSetMappingMementoImpl(
|
||||
mappingName,
|
||||
entityResultBuilders,
|
||||
instantiationResultBuilders,
|
||||
scalarResultBuilders,
|
||||
factory
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see javax.persistence.ColumnResult
|
||||
*/
|
||||
private static class JpaColumnResultMapping implements ResultMapping {
|
||||
private final String columnName;
|
||||
private final Class<?> explicitJavaType;
|
||||
|
||||
public JpaColumnResultMapping(String columnName, Class<?> explicitJavaType) {
|
||||
this.columnName = columnName;
|
||||
this.explicitJavaType = explicitJavaType == void.class
|
||||
? null
|
||||
: explicitJavaType;
|
||||
}
|
||||
|
||||
public static JpaColumnResultMapping from(ColumnResult columnResult, MetadataBuildingContext context) {
|
||||
return new JpaColumnResultMapping( columnResult.name(), columnResult.type() );
|
||||
}
|
||||
|
||||
public String getColumnName() {
|
||||
return columnName;
|
||||
}
|
||||
|
||||
public Class<?> getExplicitJavaType() {
|
||||
return explicitJavaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarResultBuilder resolve(SessionFactoryImplementor factory) {
|
||||
if ( explicitJavaType != null ) {
|
||||
final JavaTypeDescriptor<?> jtd = factory.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( explicitJavaType );
|
||||
|
||||
BootLogging.LOGGER.debugf( "ColumnResult explicit type resolved to : " + jtd );
|
||||
|
||||
return new StandardScalarResultBuilder( columnName, jtd );
|
||||
}
|
||||
|
||||
return new StandardScalarResultBuilder( columnName );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.persistence.ConstructorResult
|
||||
*/
|
||||
private static class ConstructorResultMapping implements ResultMapping {
|
||||
|
||||
public static ConstructorResultMapping from(
|
||||
ConstructorResult constructorResult,
|
||||
MetadataBuildingContext context) {
|
||||
final ColumnResult[] columnResults = constructorResult.columns();
|
||||
if ( columnResults.length == 0 ) {
|
||||
throw new IllegalArgumentException( "ConstructorResult did not define any ColumnResults" );
|
||||
}
|
||||
|
||||
final List<ResultMapping> argumentResultMappings = new ArrayList<>( columnResults.length );
|
||||
for ( int i = 0; i < columnResults.length; i++ ) {
|
||||
final ColumnResult columnResult = columnResults[i];
|
||||
argumentResultMappings.add( JpaColumnResultMapping.from( columnResult, context ) );
|
||||
}
|
||||
|
||||
return new ConstructorResultMapping(
|
||||
constructorResult.targetClass(),
|
||||
argumentResultMappings
|
||||
);
|
||||
}
|
||||
|
||||
private final Class<?> targetJavaType;
|
||||
private final List<ResultMapping> argumentResultMappings;
|
||||
|
||||
public ConstructorResultMapping(
|
||||
Class<?> targetJavaType,
|
||||
List<ResultMapping> argumentResultMappings) {
|
||||
this.targetJavaType = targetJavaType;
|
||||
this.argumentResultMappings = argumentResultMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstantiationResultBuilder resolve(SessionFactoryImplementor factory) {
|
||||
final List<ResultBuilder> argumentResultBuilders = new ArrayList<>( argumentResultMappings.size() );
|
||||
argumentResultMappings.forEach( mapping -> argumentResultBuilders.add( mapping.resolve( factory ) ) );
|
||||
|
||||
final JavaTypeDescriptor<?> targetJtd = factory.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( targetJavaType );
|
||||
|
||||
return new StandardInstantiationResultBuilder( targetJtd, argumentResultBuilders );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.persistence.EntityResult
|
||||
*/
|
||||
private static class EntityResultMapping implements ResultMapping {
|
||||
public static EntityResultMapping from(
|
||||
EntityResult entityResult,
|
||||
MetadataBuildingContext context) {
|
||||
throw new NotYetImplementedFor6Exception( "Support for dynamic-instantiation results not yet implemented" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResultBuilder resolve(SessionFactoryImplementor factory) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,347 @@
|
||||
/*
|
||||
* 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.boot.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.persistence.ColumnResult;
|
||||
import javax.persistence.ConstructorResult;
|
||||
import javax.persistence.EntityResult;
|
||||
import javax.persistence.FieldResult;
|
||||
import javax.persistence.SqlResultSetMapping;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.boot.BootLogging;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.RuntimeMetamodels;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.internal.BasicFetchMemento;
|
||||
import org.hibernate.query.internal.EntityResultMappingMemento;
|
||||
import org.hibernate.query.internal.FetchMappingMemento;
|
||||
import org.hibernate.query.internal.InstantiationResultMappingMemento;
|
||||
import org.hibernate.query.internal.InstantiationResultMappingMemento.ArgumentMemento;
|
||||
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl;
|
||||
import org.hibernate.query.internal.ResultMappingMemento;
|
||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||
import org.hibernate.query.internal.ScalarResultMappingMemento;
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescriptor {
|
||||
|
||||
// todo (6.0) : we can probably reuse the NamedResultSetMappingDefinition
|
||||
// implementation between HBM and annotation handling. We'd
|
||||
// just need different "builders" for each source and handle the
|
||||
// variances in those builders. But once we have a
|
||||
// NamedResultSetMappingDefinition and all of its sub-parts,
|
||||
// resolving to a memento is the same
|
||||
// -
|
||||
// additionally, consider having the sub-parts (the return
|
||||
// representations) be what is used and handed to the
|
||||
// NamedResultSetMappingMemento directly. They simply need
|
||||
// to be capable of resolving themselves into ResultBuilders
|
||||
// (`org.hibernate.query.results.ResultBuilder`) as part of the
|
||||
// memento for its resolution
|
||||
|
||||
@SuppressWarnings("ForLoopReplaceableByForEach")
|
||||
public static SqlResultSetMappingDescriptor from(
|
||||
SqlResultSetMapping mappingAnnotation,
|
||||
MetadataBuildingContext context) {
|
||||
|
||||
final EntityResult[] entityResults = mappingAnnotation.entities();
|
||||
final ConstructorResult[] constructorResults = mappingAnnotation.classes();
|
||||
final ColumnResult[] columnResults = mappingAnnotation.columns();
|
||||
|
||||
final List<ResultDescriptor> resultDescriptors = CollectionHelper.arrayList(
|
||||
entityResults.length + columnResults.length + columnResults.length
|
||||
);
|
||||
|
||||
for ( int i = 0; i < entityResults.length; i++ ) {
|
||||
final EntityResult entityResult = entityResults[i];
|
||||
resultDescriptors.add(
|
||||
EntityResultDescriptor.from( entityResult, context )
|
||||
);
|
||||
}
|
||||
|
||||
for ( int i = 0; i < constructorResults.length; i++ ) {
|
||||
final ConstructorResult constructorResult = constructorResults[i];
|
||||
resultDescriptors.add(
|
||||
new ConstructorResultDescriptor( constructorResult, mappingAnnotation )
|
||||
);
|
||||
}
|
||||
|
||||
for ( int i = 0; i < columnResults.length; i++ ) {
|
||||
final ColumnResult columnResult = columnResults[i];
|
||||
resultDescriptors.add(
|
||||
new JpaColumnResultDescriptor( columnResult, mappingAnnotation )
|
||||
);
|
||||
}
|
||||
|
||||
return new SqlResultSetMappingDescriptor(
|
||||
mappingAnnotation.name(),
|
||||
resultDescriptors,
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
private final String mappingName;
|
||||
private final List<ResultDescriptor> resultDescriptors;
|
||||
|
||||
private SqlResultSetMappingDescriptor(
|
||||
String mappingName,
|
||||
List<ResultDescriptor> resultDescriptors,
|
||||
MetadataBuildingContext context) {
|
||||
this.mappingName = mappingName;
|
||||
this.resultDescriptors = resultDescriptors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRegistrationName() {
|
||||
return mappingName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedResultSetMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
|
||||
final List<ResultMappingMemento> resultMementos = CollectionHelper.arrayList( resultDescriptors.size() );
|
||||
|
||||
resultDescriptors.forEach(
|
||||
resultDescriptor -> resultMementos.add( resultDescriptor.resolve( resolutionContext ) )
|
||||
);
|
||||
|
||||
return new NamedResultSetMappingMementoImpl( mappingName, resultMementos );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see javax.persistence.ColumnResult
|
||||
*/
|
||||
private static class JpaColumnResultDescriptor implements ResultDescriptor {
|
||||
private final ColumnResult columnResult;
|
||||
private final String mappingName;
|
||||
|
||||
public JpaColumnResultDescriptor(
|
||||
ColumnResult columnResult,
|
||||
SqlResultSetMapping mappingAnnotation) {
|
||||
this.columnResult = columnResult;
|
||||
this.mappingName = mappingAnnotation.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
|
||||
BootLogging.LOGGER.debugf(
|
||||
"Generating ScalarResultMappingMemento for JPA ColumnResult(%s) for ResultSet mapping `%s`",
|
||||
columnResult.name(),
|
||||
mappingName
|
||||
);
|
||||
|
||||
return new ScalarResultMappingMemento( columnResult, resolutionContext );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.persistence.ConstructorResult
|
||||
*/
|
||||
private static class ConstructorResultDescriptor implements ResultDescriptor {
|
||||
private static class ArgumentDescriptor {
|
||||
private final JpaColumnResultDescriptor argumentResultDescriptor;
|
||||
|
||||
private ArgumentDescriptor(JpaColumnResultDescriptor argumentResultDescriptor) {
|
||||
this.argumentResultDescriptor = argumentResultDescriptor;
|
||||
}
|
||||
|
||||
ArgumentMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
|
||||
return new ArgumentMemento( argumentResultDescriptor.resolve( resolutionContext ) );
|
||||
}
|
||||
}
|
||||
|
||||
private final String mappingName;
|
||||
|
||||
private final Class<?> targetJavaType;
|
||||
private final List<ArgumentDescriptor> argumentResultDescriptors;
|
||||
|
||||
public ConstructorResultDescriptor(
|
||||
ConstructorResult constructorResult,
|
||||
SqlResultSetMapping mappingAnnotation) {
|
||||
this.mappingName = mappingAnnotation.name();
|
||||
this.targetJavaType = constructorResult.targetClass();
|
||||
|
||||
final ColumnResult[] columnResults = constructorResult.columns();
|
||||
if ( columnResults.length == 0 ) {
|
||||
throw new IllegalArgumentException( "ConstructorResult did not define any ColumnResults" );
|
||||
}
|
||||
|
||||
this.argumentResultDescriptors = CollectionHelper.arrayList( columnResults.length );
|
||||
for ( int i = 0; i < columnResults.length; i++ ) {
|
||||
final ColumnResult columnResult = columnResults[i];
|
||||
final JpaColumnResultDescriptor argumentResultDescriptor = new JpaColumnResultDescriptor(
|
||||
columnResult,
|
||||
mappingAnnotation
|
||||
);
|
||||
argumentResultDescriptors.add( new ArgumentDescriptor( argumentResultDescriptor ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
|
||||
BootLogging.LOGGER.debugf(
|
||||
"Generating InstantiationResultMappingMemento for JPA ConstructorResult(%s) for ResultSet mapping `%s`",
|
||||
targetJavaType.getName(),
|
||||
mappingName
|
||||
);
|
||||
|
||||
final List<ArgumentMemento> argumentResultMementos = new ArrayList<>( argumentResultDescriptors.size() );
|
||||
|
||||
argumentResultDescriptors.forEach(
|
||||
(mapping) -> argumentResultMementos.add( mapping.resolve( resolutionContext ) )
|
||||
);
|
||||
|
||||
final SessionFactoryImplementor sessionFactory = resolutionContext.getSessionFactory();
|
||||
final JavaTypeDescriptor<?> targetJtd = sessionFactory.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( targetJavaType );
|
||||
|
||||
return new InstantiationResultMappingMemento( targetJtd, argumentResultMementos );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.persistence.EntityResult
|
||||
*/
|
||||
public static class EntityResultDescriptor implements ResultDescriptor {
|
||||
private final NavigablePath navigablePath;
|
||||
|
||||
private final String entityName;
|
||||
private final String discriminatorColumn;
|
||||
|
||||
private final Map<String, AttributeFetchDescriptor> fetchMappings;
|
||||
|
||||
public static EntityResultDescriptor from(EntityResult entityResult, MetadataBuildingContext context) {
|
||||
final String entityName = entityResult.entityClass().getName();
|
||||
|
||||
final Map<String, AttributeFetchDescriptor> fetchMappings = new HashMap<>();
|
||||
for ( int i = 0; i < entityResult.fields().length; i++ ) {
|
||||
final FieldResult fieldResult = entityResult.fields()[ i ];
|
||||
final AttributeFetchDescriptor existing = fetchMappings.get( fieldResult.name() );
|
||||
if ( existing != null ) {
|
||||
existing.addColumn( fieldResult );
|
||||
}
|
||||
else {
|
||||
fetchMappings.put(
|
||||
fieldResult.name(),
|
||||
AttributeFetchDescriptor.from( entityName, fieldResult, context )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new EntityResultDescriptor(
|
||||
entityName,
|
||||
entityResult.discriminatorColumn(),
|
||||
fetchMappings
|
||||
);
|
||||
}
|
||||
|
||||
public EntityResultDescriptor(
|
||||
String entityName,
|
||||
String discriminatorColumn,
|
||||
Map<String, AttributeFetchDescriptor> fetchMappings) {
|
||||
this.navigablePath = new NavigablePath( entityName );
|
||||
|
||||
this.entityName = entityName;
|
||||
this.discriminatorColumn = discriminatorColumn;
|
||||
|
||||
this.fetchMappings = fetchMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultMappingMemento resolve(ResultSetMappingResolutionContext resolutionContext) {
|
||||
final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels();
|
||||
final EntityMappingType entityDescriptor = runtimeMetamodels.getEntityMappingType( entityName );
|
||||
|
||||
final Map<String, FetchMappingMemento> fetchMementos = new HashMap<>();
|
||||
fetchMappings.forEach(
|
||||
(attrName, attrMapping) -> fetchMementos.put( attrName, attrMapping.resolve( resolutionContext ) )
|
||||
);
|
||||
|
||||
return new EntityResultMappingMemento( entityDescriptor, discriminatorColumn, fetchMementos );
|
||||
}
|
||||
}
|
||||
|
||||
private static class AttributeFetchDescriptor implements FetchDescriptor {
|
||||
|
||||
private static AttributeFetchDescriptor from(
|
||||
String entityName,
|
||||
FieldResult fieldResult,
|
||||
MetadataBuildingContext context) {
|
||||
return new AttributeFetchDescriptor(
|
||||
entityName,
|
||||
fieldResult.name(),
|
||||
fieldResult.column()
|
||||
);
|
||||
}
|
||||
|
||||
private final String entityName;
|
||||
private final String attributeName;
|
||||
private final List<String> columnNames;
|
||||
|
||||
private AttributeFetchDescriptor(String entityName, String attributeName, String columnName) {
|
||||
this.entityName = entityName;
|
||||
this.attributeName = attributeName;
|
||||
this.columnNames = new ArrayList<>();
|
||||
columnNames.add( columnName );
|
||||
}
|
||||
|
||||
private void addColumn(FieldResult fieldResult) {
|
||||
if ( ! attributeName.equals( fieldResult.name() ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Passed FieldResult [%s, %s] does not match AttributeFetchMapping [%s]",
|
||||
fieldResult.name(),
|
||||
fieldResult.column(),
|
||||
attributeName
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
columnNames.add( fieldResult.column() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchMappingMemento 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 BasicFetchMemento( basicPart, columnNames.get( 0 ) );
|
||||
}
|
||||
|
||||
throw new NotYetImplementedFor6Exception(
|
||||
"Only support for basic-valued model-parts have been implemented : " + attributeName + " [" + subPart + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedProcedureCallDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDescriptor;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
@ -144,12 +144,12 @@ public void visitNamedProcedureCallDefinition(Consumer<NamedProcedureCallDefinit
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedResultSetMappingDefinition getResultSetMapping(String name) {
|
||||
public NamedResultSetMappingDescriptor getResultSetMapping(String name) {
|
||||
return delegate.getResultSetMapping( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDefinition> definitionConsumer) {
|
||||
public void visitNamedResultSetMappingDefinition(Consumer<NamedResultSetMappingDescriptor> definitionConsumer) {
|
||||
delegate.visitNamedResultSetMappingDefinition( definitionConsumer );
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedProcedureCallDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDescriptor;
|
||||
import org.hibernate.cfg.AnnotatedClassType;
|
||||
import org.hibernate.cfg.AttributeConverterDefinition;
|
||||
import org.hibernate.cfg.JPAIndexHolder;
|
||||
@ -154,7 +154,7 @@ Table addDenormalizedTable(
|
||||
/**
|
||||
* Adds the metadata for a named SQL result set mapping to this collector.
|
||||
*/
|
||||
void addResultSetMapping(NamedResultSetMappingDefinition resultSetMappingDefinition) throws DuplicateMappingException;
|
||||
void addResultSetMapping(NamedResultSetMappingDescriptor resultSetMappingDefinition) throws DuplicateMappingException;
|
||||
|
||||
/**
|
||||
* Adds metadata for a named stored procedure call to this collector.
|
||||
@ -271,7 +271,7 @@ void addTableNameBinding(
|
||||
|
||||
void addDefaultNamedNativeQuery(NamedNativeQueryDefinition query);
|
||||
|
||||
void addDefaultResultSetMapping(NamedResultSetMappingDefinition definition);
|
||||
void addDefaultResultSetMapping(NamedResultSetMappingDescriptor definition);
|
||||
|
||||
void addDefaultNamedProcedureCall(NamedProcedureCallDefinitionImpl procedureCallDefinition);
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
import org.hibernate.boot.query.NamedHqlQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedNativeQueryDefinition;
|
||||
import org.hibernate.boot.query.NamedProcedureCallDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
|
||||
import org.hibernate.boot.query.NamedResultSetMappingDescriptor;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
@ -100,7 +100,7 @@ public class Configuration {
|
||||
private Map<String, NamedHqlQueryDefinition> namedQueries;
|
||||
private Map<String, NamedNativeQueryDefinition> namedSqlQueries;
|
||||
private Map<String, NamedProcedureCallDefinition> namedProcedureCallMap;
|
||||
private Map<String, NamedResultSetMappingDefinition> sqlResultSetMappings;
|
||||
private Map<String, NamedResultSetMappingDescriptor> sqlResultSetMappings;
|
||||
private Map<String, NamedEntityGraphDefinition> namedEntityGraphMap;
|
||||
|
||||
private Map<String, SqmFunctionDescriptor> customFunctionDescriptors;
|
||||
|
@ -22,7 +22,7 @@
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.ToOne;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.boot.query.SqlResultSetMappingDefinition;
|
||||
import org.hibernate.boot.query.SqlResultSetMappingDescriptor;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
@ -46,7 +46,7 @@ public void doSecondPass(Map persistentClasses) throws MappingException {
|
||||
return;
|
||||
}
|
||||
|
||||
final SqlResultSetMappingDefinition mappingDefinition = SqlResultSetMappingDefinition.from( ann, context );
|
||||
final SqlResultSetMappingDescriptor mappingDefinition = SqlResultSetMappingDescriptor.from( ann, context );
|
||||
|
||||
if ( isDefault ) {
|
||||
context.getMetadataCollector().addDefaultResultSetMapping( mappingDefinition );
|
||||
|
@ -131,7 +131,7 @@ public ProcedureCallImpl(SharedSessionContractImplementor session, String proced
|
||||
resultClasses,
|
||||
resultSetMapping,
|
||||
synchronizedQuerySpaces::add,
|
||||
getSession().getFactory()
|
||||
() -> getSession().getFactory()
|
||||
);
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ public ProcedureCallImpl(
|
||||
resultSetMappingNames,
|
||||
resultSetMapping,
|
||||
synchronizedQuerySpaces::add,
|
||||
getSession().getFactory()
|
||||
() -> getSession().getFactory()
|
||||
);
|
||||
}
|
||||
|
||||
@ -186,7 +186,7 @@ public ProcedureCallImpl(
|
||||
memento.getResultSetMappingClasses(),
|
||||
resultSetMapping,
|
||||
synchronizedQuerySpaces::add,
|
||||
getSession().getFactory()
|
||||
() -> getSession().getFactory()
|
||||
);
|
||||
|
||||
applyOptions( memento );
|
||||
@ -216,7 +216,7 @@ public ProcedureCallImpl(
|
||||
resultTypes,
|
||||
resultSetMapping,
|
||||
synchronizedQuerySpaces::add,
|
||||
getSession().getFactory()
|
||||
() -> getSession().getFactory()
|
||||
);
|
||||
|
||||
applyOptions( memento );
|
||||
@ -240,7 +240,7 @@ public ProcedureCallImpl(
|
||||
null,
|
||||
resultSetMapping,
|
||||
synchronizedQuerySpaces::add,
|
||||
getSession().getFactory()
|
||||
() -> getSession().getFactory()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -9,12 +9,11 @@
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||
import org.hibernate.query.named.NamedQueryRepository;
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.results.ResultSetMapping;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
@ -34,16 +33,16 @@ public static void resolveResultSetMappings(
|
||||
Class[] resultSetMappingClasses,
|
||||
ResultSetMapping resultSetMapping,
|
||||
Consumer<String> querySpaceConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
ResultSetMappingResolutionContext context) {
|
||||
if ( ! ArrayHelper.isEmpty( resultSetMappingNames ) ) {
|
||||
// cannot specify both
|
||||
if ( ! ArrayHelper.isEmpty( resultSetMappingClasses ) ) {
|
||||
throw new IllegalArgumentException( "Cannot specify both result-set mapping names and classes" );
|
||||
}
|
||||
resolveResultSetMappingNames( resultSetMappingNames, resultSetMapping, querySpaceConsumer, sessionFactory );
|
||||
resolveResultSetMappingNames( resultSetMappingNames, resultSetMapping, querySpaceConsumer, context );
|
||||
}
|
||||
else if ( ! ArrayHelper.isEmpty( resultSetMappingClasses ) ) {
|
||||
resolveResultSetMappingClasses( resultSetMappingClasses, resultSetMapping, querySpaceConsumer, sessionFactory );
|
||||
resolveResultSetMappingClasses( resultSetMappingClasses, resultSetMapping, querySpaceConsumer, context );
|
||||
}
|
||||
|
||||
// otherwise, nothing to resolve
|
||||
@ -53,15 +52,15 @@ public static void resolveResultSetMappingNames(
|
||||
String[] resultSetMappingNames,
|
||||
ResultSetMapping resultSetMapping,
|
||||
Consumer<String> querySpaceConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final NamedQueryRepository namedQueryRepository = sessionFactory.getQueryEngine().getNamedQueryRepository();
|
||||
ResultSetMappingResolutionContext context) {
|
||||
final NamedQueryRepository namedQueryRepository = context.getSessionFactory().getQueryEngine().getNamedQueryRepository();
|
||||
|
||||
for ( String resultSetMappingName : resultSetMappingNames ) {
|
||||
final NamedResultSetMappingMemento memento = namedQueryRepository.getResultSetMappingMemento( resultSetMappingName );
|
||||
memento.resolve(
|
||||
resultSetMapping,
|
||||
querySpaceConsumer,
|
||||
sessionFactory
|
||||
context
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -70,7 +69,7 @@ public static void resolveResultSetMappingClasses(
|
||||
Class[] resultSetMappingClasses,
|
||||
ResultSetMapping resultSetMapping,
|
||||
Consumer<String> querySpaceConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
ResultSetMappingResolutionContext context) {
|
||||
throw new NotYetImplementedFor6Exception( Util.class );
|
||||
|
||||
// final DomainMetamodel domainModel = sessionFactory.getDomainModel();
|
||||
|
@ -118,6 +118,19 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
|
||||
*/
|
||||
<C> NativeQuery<T> addScalar(String columnAlias, Class<C> relationalJavaType, AttributeConverter<?,C> converter);
|
||||
|
||||
/**
|
||||
* Declare a scalar query result with an explicit conversion
|
||||
*
|
||||
* @param jdbcJavaType The Java type expected by the converter as its "relational model" type.
|
||||
* @param domainJavaType The Java type expected by the converter as its "object model" type.
|
||||
* @param converter The conversion to apply. Consumes the JDBC value based on `relationalJavaType`.
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
<O,R> NativeQuery<T> addScalar(String columnAlias, Class<O> domainJavaType, Class<R> jdbcJavaType, AttributeConverter<O,R> converter);
|
||||
|
||||
/**
|
||||
* Declare a scalar query result with an explicit conversion
|
||||
*
|
||||
@ -132,6 +145,25 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
|
||||
*/
|
||||
<C> NativeQuery<T> addScalar(String columnAlias, Class<C> relationalJavaType, Class<? extends AttributeConverter<?,C>> converter);
|
||||
|
||||
/**
|
||||
* Declare a scalar query result with an explicit conversion
|
||||
*
|
||||
* @param jdbcJavaType The Java type expected by the converter as its "relational model" type.
|
||||
* @param domainJavaType The Java type expected by the converter as its "object model" type.
|
||||
* @param converter The conversion to apply. Consumes the JDBC value based on `jdbcJavaType`.
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
<O,R> NativeQuery<T> addScalar(
|
||||
String columnAlias,
|
||||
Class<O> domainJavaType,
|
||||
Class<R> jdbcJavaType,
|
||||
Class<? extends AttributeConverter<O,R>> converter);
|
||||
|
||||
<J> InstantiationResultNode<J> addInstantiation(Class<J> targetJavaType);
|
||||
|
||||
/**
|
||||
* Defines a result based on a specified attribute. Differs from adding a scalar in that
|
||||
* any conversions or other semantics defined on the attribute are automatically applied
|
||||
@ -321,6 +353,14 @@ interface ResultNode {
|
||||
interface ReturnableResultNode extends ResultNode {
|
||||
}
|
||||
|
||||
interface InstantiationResultNode<J> extends ReturnableResultNode {
|
||||
default InstantiationResultNode<J> addBasicArgument(String columnAlias) {
|
||||
return addBasicArgument( columnAlias, null );
|
||||
}
|
||||
|
||||
InstantiationResultNode<J> addBasicArgument(String columnAlias, String argumentAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows access to further control how properties within a root or join
|
||||
* fetch are mapped back from the result set. Generally used in composite
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.results.FetchBuilder;
|
||||
import org.hibernate.query.results.complete.CompleteFetchBuilderBasicPart;
|
||||
|
||||
/**
|
||||
* Memento describing a basic-valued fetch. A basic-value cannot be
|
||||
* de-referenced.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BasicFetchMemento implements FetchMappingMemento {
|
||||
private final BasicValuedModelPart fetchedAttribute;
|
||||
private final String columnAlias;
|
||||
|
||||
public BasicFetchMemento(BasicValuedModelPart fetchedAttribute, String columnAlias) {
|
||||
this.fetchedAttribute = fetchedAttribute;
|
||||
this.columnAlias = columnAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder resolve(
|
||||
Parent parent,
|
||||
Consumer<String> querySpaceConsumer,
|
||||
ResultSetMappingResolutionContext context) {
|
||||
return new CompleteFetchBuilderBasicPart( fetchedAttribute, columnAlias );
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 );
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.ManagedMappingType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface FetchMappingMemento {
|
||||
interface Parent {
|
||||
/**
|
||||
* The path for the parent
|
||||
*/
|
||||
NavigablePath getNavigablePath();
|
||||
|
||||
/**
|
||||
* The entity descriptor that is the base for this path/parent
|
||||
*/
|
||||
ManagedMappingType getMappingType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the fetch-memento into the result-graph-node builder
|
||||
*/
|
||||
FetchBuilder resolve(Parent parent, Consumer<String> querySpaceConsumer, ResultSetMappingResolutionContext context);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.complete.CompleteResultBuilderInstantiation;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class InstantiationResultMappingMemento implements ResultMappingMemento {
|
||||
public static class ArgumentMemento {
|
||||
private final ResultMappingMemento argumentMemento;
|
||||
|
||||
public ArgumentMemento(ResultMappingMemento argumentMemento) {
|
||||
this.argumentMemento = argumentMemento;
|
||||
}
|
||||
|
||||
public ResultBuilder resolve(Consumer<String> querySpaceConsumer, ResultSetMappingResolutionContext context) {
|
||||
return argumentMemento.resolve( querySpaceConsumer, context );
|
||||
}
|
||||
}
|
||||
|
||||
private final JavaTypeDescriptor<?> instantiatedJtd;
|
||||
private final List<ArgumentMemento> argumentMementos;
|
||||
|
||||
public InstantiationResultMappingMemento(
|
||||
JavaTypeDescriptor<?> instantiatedJtd,
|
||||
List<ArgumentMemento> argumentMementos) {
|
||||
this.instantiatedJtd = instantiatedJtd;
|
||||
this.argumentMementos = argumentMementos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder resolve(
|
||||
Consumer<String> querySpaceConsumer,
|
||||
ResultSetMappingResolutionContext context) {
|
||||
final List<ResultBuilder> argumentBuilders = CollectionHelper.arrayList( argumentMementos.size() );
|
||||
|
||||
argumentMementos.forEach(
|
||||
argumentMemento -> argumentBuilders.add(
|
||||
argumentMemento.resolve( querySpaceConsumer, context )
|
||||
)
|
||||
);
|
||||
|
||||
return new CompleteResultBuilderInstantiation( instantiatedJtd, argumentBuilders );
|
||||
}
|
||||
}
|
@ -153,9 +153,16 @@ public void prepare(
|
||||
}
|
||||
);
|
||||
|
||||
final ResultSetMappingResolutionContext resolutionContext = new ResultSetMappingResolutionContext() {
|
||||
@Override
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return sessionFactory;
|
||||
}
|
||||
};
|
||||
|
||||
bootMetamodel.visitNamedResultSetMappingDefinition(
|
||||
namedResultSetMappingDefinition -> {
|
||||
final NamedResultSetMappingMemento resolved = namedResultSetMappingDefinition.resolve( sessionFactory );
|
||||
final NamedResultSetMappingMemento resolved = namedResultSetMappingDefinition.resolve( resolutionContext );
|
||||
resultSetMappingMementoMap.put( namedResultSetMappingDefinition.getRegistrationName(), resolved );
|
||||
}
|
||||
);
|
||||
|
@ -6,17 +6,11 @@
|
||||
*/
|
||||
package org.hibernate.query.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.results.EntityResultBuilder;
|
||||
import org.hibernate.query.results.InstantiationResultBuilder;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultSetMapping;
|
||||
import org.hibernate.query.results.ScalarResultBuilder;
|
||||
|
||||
/**
|
||||
* Standard `NamedResultSetMappingMemento` implementation
|
||||
@ -25,25 +19,13 @@
|
||||
*/
|
||||
public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMemento {
|
||||
private final String name;
|
||||
|
||||
private final List<ResultBuilder> resultBuilders;
|
||||
private final List<ResultMappingMemento> resultMappingMementos;
|
||||
|
||||
public NamedResultSetMappingMementoImpl(
|
||||
String name,
|
||||
List<EntityResultBuilder> entityResultBuilders,
|
||||
List<InstantiationResultBuilder> instantiationResultBuilders,
|
||||
List<ScalarResultBuilder> scalarResultBuilders,
|
||||
SessionFactoryImplementor factory) {
|
||||
List<ResultMappingMemento> resultMappingMementos) {
|
||||
this.name = name;
|
||||
|
||||
final int totalNumberOfBuilders = entityResultBuilders.size()
|
||||
+ instantiationResultBuilders.size()
|
||||
+ scalarResultBuilders.size();
|
||||
this.resultBuilders = new ArrayList<>( totalNumberOfBuilders );
|
||||
|
||||
resultBuilders.addAll( entityResultBuilders );
|
||||
resultBuilders.addAll( instantiationResultBuilders );
|
||||
resultBuilders.addAll( scalarResultBuilders );
|
||||
this.resultMappingMementos = resultMappingMementos;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -55,7 +37,9 @@ public String getName() {
|
||||
public void resolve(
|
||||
ResultSetMapping resultSetMapping,
|
||||
Consumer<String> querySpaceConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
resultBuilders.forEach( resultSetMapping::addResultBuilder );
|
||||
ResultSetMappingResolutionContext context) {
|
||||
resultMappingMementos.forEach(
|
||||
memento -> resultSetMapping.addResultBuilder( memento.resolve( querySpaceConsumer, context ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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.internal;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ResultMappingMemento {
|
||||
ResultBuilder resolve(Consumer<String> querySpaceConsumer, ResultSetMappingResolutionContext context);
|
||||
}
|
@ -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.internal;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
/**
|
||||
* Context ("parameter object") used in resolving a {@link NamedResultSetMappingMementoImpl}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ResultSetMappingResolutionContext {
|
||||
SessionFactoryImplementor getSessionFactory();
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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 javax.persistence.ColumnResult;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.complete.CompleteResultBuilderBasicValuedStandard;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Implementation of ResultMappingMemento for scalar (basic) results.
|
||||
*
|
||||
* Ultimately a scalar result is defined as a column name and a BasicType with the following notes:<ul>
|
||||
* <li>
|
||||
* For JPA mappings, the column name is required. For `hbm.xml` mappings, it is optional (positional)
|
||||
* </li>
|
||||
* <li>
|
||||
* Ultimately, when reading values, we need the {@link BasicType}. We know the BasicType in a few
|
||||
* different ways:<ul>
|
||||
* <li>
|
||||
* If we know an explicit Type, that is used.
|
||||
* </li>
|
||||
* <li>
|
||||
* If we do not know the Type, but do know the Java type then we determine the BasicType
|
||||
* based on the reported SQL type and its known mapping to the specified Java type
|
||||
* </li>
|
||||
* <li>
|
||||
* If we know neither, we use the reported SQL type and its recommended Java type to
|
||||
* resolve the BasicType to use
|
||||
* </li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ScalarResultMappingMemento implements ResultMappingMemento {
|
||||
|
||||
public final String explicitColumnName;
|
||||
|
||||
private final BasicType<?> explicitType;
|
||||
private final JavaTypeDescriptor<?> explicitJavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Creation of ScalarResultMappingMemento for JPA descriptor
|
||||
*/
|
||||
public ScalarResultMappingMemento(
|
||||
ColumnResult definition,
|
||||
ResultSetMappingResolutionContext context) {
|
||||
this.explicitColumnName = definition.name();
|
||||
|
||||
final Class<?> definedType = definition.type();
|
||||
if ( void.class == definedType ) {
|
||||
explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
else {
|
||||
final SessionFactoryImplementor sessionFactory = context.getSessionFactory();
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
this.explicitJavaTypeDescriptor = jtdRegistry.getDescriptor( definition.type() );
|
||||
}
|
||||
|
||||
explicitType = null;
|
||||
}
|
||||
|
||||
public ScalarResultMappingMemento(
|
||||
String explicitColumnName,
|
||||
BasicType<?> explicitType,
|
||||
ResultSetMappingResolutionContext context) {
|
||||
this.explicitColumnName = explicitColumnName;
|
||||
this.explicitType = explicitType;
|
||||
this.explicitJavaTypeDescriptor = explicitType != null
|
||||
? explicitType.getJavaTypeDescriptor()
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultBuilder resolve(
|
||||
Consumer<String> querySpaceConsumer,
|
||||
ResultSetMappingResolutionContext context) {
|
||||
return new CompleteResultBuilderBasicValuedStandard( this, context );
|
||||
}
|
||||
|
||||
public String getExplicitColumnName() {
|
||||
return explicitColumnName;
|
||||
}
|
||||
|
||||
public BasicType<?> getExplicitType() {
|
||||
return explicitType;
|
||||
}
|
||||
|
||||
public JavaTypeDescriptor<?> getExplicitJavaTypeDescriptor() {
|
||||
return explicitJavaTypeDescriptor;
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||
import org.hibernate.query.results.ResultSetMapping;
|
||||
|
||||
/**
|
||||
@ -38,5 +38,8 @@ public interface NamedResultSetMappingMemento {
|
||||
* each defined result and registering them with the passed `resultSetMapping`. Any known
|
||||
* query spaces should be passed to the `querySpaceConsumer`
|
||||
*/
|
||||
void resolve(ResultSetMapping resultSetMapping, Consumer<String> querySpaceConsumer, SessionFactoryImplementor sessionFactory);
|
||||
void resolve(
|
||||
ResultSetMapping resultSetMapping,
|
||||
Consumer<String> querySpaceConsumer,
|
||||
ResultSetMappingResolutionContext context);
|
||||
}
|
||||
|
@ -16,8 +16,17 @@
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.RuntimeMetamodels;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.results.dynamic.DynamicResultBuilderAttribute;
|
||||
import org.hibernate.query.results.dynamic.DynamicResultBuilderBasic;
|
||||
import org.hibernate.query.results.dynamic.DynamicResultBuilderBasicConverted;
|
||||
import org.hibernate.query.results.dynamic.DynamicResultBuilderBasicStandard;
|
||||
import org.hibernate.query.results.dynamic.DynamicResultBuilderEntityCalculated;
|
||||
import org.hibernate.query.results.dynamic.DynamicResultBuilderEntityStandard;
|
||||
import org.hibernate.query.results.dynamic.DynamicResultBuilderInstantiation;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
@ -25,53 +34,92 @@
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Builders {
|
||||
public static ScalarResultBuilder scalar(String columnAlias) {
|
||||
return new StandardScalarResultBuilder( columnAlias );
|
||||
public static DynamicResultBuilderBasic scalar(String columnAlias) {
|
||||
return scalar( columnAlias, columnAlias );
|
||||
}
|
||||
|
||||
public static ScalarResultBuilder scalar(
|
||||
String columnAlias,
|
||||
BasicType<?> type) {
|
||||
return new StandardScalarResultBuilder( columnAlias, type );
|
||||
public static DynamicResultBuilderBasic scalar(String columnAlias, String resultAlias) {
|
||||
return new DynamicResultBuilderBasicStandard( columnAlias, resultAlias );
|
||||
}
|
||||
|
||||
public static ScalarResultBuilder scalar(
|
||||
public static DynamicResultBuilderBasic scalar(String columnAlias, BasicType<?> type) {
|
||||
return scalar( columnAlias, columnAlias, type );
|
||||
}
|
||||
|
||||
public static DynamicResultBuilderBasic scalar(String columnAlias, String resultAlias, BasicType<?> type) {
|
||||
return new DynamicResultBuilderBasicStandard( columnAlias, resultAlias, type );
|
||||
}
|
||||
|
||||
public static DynamicResultBuilderBasic scalar(
|
||||
String columnAlias,
|
||||
Class<?> javaType,
|
||||
SessionFactoryImplementor factory) {
|
||||
return scalar( columnAlias, columnAlias, javaType, factory );
|
||||
}
|
||||
|
||||
public static DynamicResultBuilderBasic scalar(
|
||||
String columnAlias,
|
||||
String resultAlias,
|
||||
Class<?> javaType,
|
||||
SessionFactoryImplementor factory) {
|
||||
final JavaTypeDescriptor<?> javaTypeDescriptor = factory.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( javaType );
|
||||
|
||||
return new StandardScalarResultBuilder( columnAlias, javaTypeDescriptor );
|
||||
return new DynamicResultBuilderBasicStandard( columnAlias, resultAlias, javaTypeDescriptor );
|
||||
}
|
||||
|
||||
public static <C> ResultBuilder scalar(
|
||||
public static <R> ResultBuilder converted(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
AttributeConverter<?, C> converter,
|
||||
Class<R> jdbcJavaType,
|
||||
AttributeConverter<?, R> converter,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
return ConvertedResultBuilder.from( columnAlias, relationalJavaType, converter, sessionFactory );
|
||||
return converted( columnAlias, null, jdbcJavaType, converter, sessionFactory );
|
||||
}
|
||||
|
||||
public static <C> ResultBuilder scalar(
|
||||
public static <O,R> ResultBuilder converted(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
Class<? extends AttributeConverter<?, C>> converterJavaType,
|
||||
Class<O> domainJavaType,
|
||||
Class<R> jdbcJavaType,
|
||||
AttributeConverter<O, R> converter,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
return ConvertedResultBuilder.from( columnAlias, relationalJavaType, converterJavaType, sessionFactory );
|
||||
return new DynamicResultBuilderBasicConverted( columnAlias, domainJavaType, jdbcJavaType, converter, sessionFactory );
|
||||
}
|
||||
|
||||
public static ScalarResultBuilder scalar(int position) {
|
||||
public static <R> ResultBuilder converted(
|
||||
String columnAlias,
|
||||
Class<R> jdbcJavaType,
|
||||
Class<? extends AttributeConverter<?, R>> converterJavaType,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
return converted( columnAlias, null, jdbcJavaType, (Class) converterJavaType, sessionFactory );
|
||||
}
|
||||
|
||||
public static <O,R> ResultBuilder converted(
|
||||
String columnAlias,
|
||||
Class<O> domainJavaType,
|
||||
Class<R> jdbcJavaType,
|
||||
Class<? extends AttributeConverter<O,R>> converterJavaType,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
return new DynamicResultBuilderBasicConverted( columnAlias, domainJavaType, jdbcJavaType, converterJavaType, sessionFactory );
|
||||
}
|
||||
|
||||
public static ResultBuilderBasicValued scalar(int position) {
|
||||
// will be needed for interpreting legacy HBM <resultset/> mappings
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
|
||||
public static ScalarResultBuilder scalar(int position, BasicType<?> type) {
|
||||
public static ResultBuilderBasicValued scalar(int position, BasicType<?> type) {
|
||||
// will be needed for interpreting legacy HBM <resultset/> mappings
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
|
||||
public static <J> DynamicResultBuilderInstantiation<J> instantiation(Class<J> targetJavaType, SessionFactoryImplementor factory) {
|
||||
final JavaTypeDescriptor<J> targetJtd = factory.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.getDescriptor( targetJavaType );
|
||||
return new DynamicResultBuilderInstantiation<>( targetJtd );
|
||||
}
|
||||
|
||||
public static ResultBuilder attributeResult(
|
||||
String columnAlias,
|
||||
String entityName,
|
||||
@ -97,7 +145,7 @@ public static ResultBuilder attributeResult(
|
||||
|
||||
if ( attributeMapping instanceof SingularAttributeMapping ) {
|
||||
final SingularAttributeMapping singularAttributeMapping = (SingularAttributeMapping) attributeMapping;
|
||||
return new AttributeResultBuilder( singularAttributeMapping, columnAlias, fullEntityName, attributePath );
|
||||
return new DynamicResultBuilderAttribute( singularAttributeMapping, columnAlias, fullEntityName, attributePath );
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
@ -128,8 +176,14 @@ public static ResultBuilder attributeResult(String columnAlias, SingularAttribut
|
||||
* @param entityName
|
||||
* @return
|
||||
*/
|
||||
public static EntityResultBuilder entity(String tableAlias, String entityName) {
|
||||
throw new NotYetImplementedFor6Exception( );
|
||||
public static DynamicResultBuilderEntityStandard entity(
|
||||
String tableAlias,
|
||||
String entityName,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final RuntimeMetamodels runtimeMetamodels = sessionFactory.getRuntimeMetamodels();
|
||||
final EntityMappingType entityMapping = runtimeMetamodels.getEntityMappingType( entityName );
|
||||
|
||||
return new DynamicResultBuilderEntityStandard( entityMapping, tableAlias );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,25 +194,32 @@ public static EntityResultBuilder entity(String tableAlias, String entityName) {
|
||||
* @see org.hibernate.query.NativeQuery#addEntity(String, Class)
|
||||
* @see org.hibernate.query.NativeQuery#addEntity(String, String)
|
||||
*/
|
||||
public static CalculatedEntityResultBuilder entityCalculated(String tableAlias, String entityName) {
|
||||
return entityCalculated( tableAlias, entityName, null );
|
||||
public static DynamicResultBuilderEntityCalculated entityCalculated(
|
||||
String tableAlias,
|
||||
String entityName,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
return entityCalculated( tableAlias, entityName, null,sessionFactory );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a EntityResultBuilder that does not allow any further configuring of the mapping.
|
||||
*
|
||||
* @see #entityCalculated(String, String)
|
||||
* @see #entityCalculated(String, String, SessionFactoryImplementor)
|
||||
* @see org.hibernate.query.NativeQuery#addEntity(String, Class, LockMode)
|
||||
* @see org.hibernate.query.NativeQuery#addEntity(String, String, LockMode)
|
||||
*/
|
||||
public static CalculatedEntityResultBuilder entityCalculated(
|
||||
public static DynamicResultBuilderEntityCalculated entityCalculated(
|
||||
String tableAlias,
|
||||
String entityName,
|
||||
LockMode explicitLockMode) {
|
||||
return new CalculatedEntityResultBuilder( tableAlias, entityName, explicitLockMode );
|
||||
LockMode explicitLockMode,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final RuntimeMetamodels runtimeMetamodels = sessionFactory.getRuntimeMetamodels();
|
||||
final EntityMappingType entityMapping = runtimeMetamodels.getEntityMappingType( entityName );
|
||||
|
||||
return new DynamicResultBuilderEntityCalculated( entityMapping, tableAlias, explicitLockMode, sessionFactory );
|
||||
}
|
||||
|
||||
public static LegacyFetchBuilder fetch(String tableAlias, String ownerTableAlias, String joinPropertyName) {
|
||||
public static DynamicFetchBuilderLegacy fetch(String tableAlias, String ownerTableAlias, String joinPropertyName) {
|
||||
throw new NotYetImplementedFor6Exception( );
|
||||
}
|
||||
}
|
||||
|
@ -1,46 +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.results;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* An entity DomainResult builder for cases when Hibernate implicitly
|
||||
* calculates the mapping
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CalculatedEntityResultBuilder implements ResultBuilder {
|
||||
private final String tableAlias;
|
||||
private final String entityName;
|
||||
private final LockMode explicitLockMode;
|
||||
|
||||
public CalculatedEntityResultBuilder(
|
||||
String tableAlias,
|
||||
String entityName,
|
||||
LockMode explicitLockMode) {
|
||||
this.tableAlias = tableAlias;
|
||||
this.entityName = entityName;
|
||||
this.explicitLockMode = explicitLockMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildReturn(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,200 +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.results;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.converter.ConvertedValueExtractor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* A ResultBuilder for explicitly converted scalar results
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ConvertedResultBuilder implements ScalarResultBuilder {
|
||||
|
||||
public static <C> ResultBuilder from(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
AttributeConverter<?, C> converter,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
final JavaTypeDescriptor<C> relationJtd = jtdRegistry.getDescriptor( relationalJavaType );
|
||||
|
||||
return new ConvertedResultBuilder( columnAlias, relationJtd, converter );
|
||||
}
|
||||
|
||||
public static <C> ResultBuilder from(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
Class<? extends AttributeConverter<?, C>> converterJavaType,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
final JavaTypeDescriptor<C> relationJtd = jtdRegistry.getDescriptor( relationalJavaType );
|
||||
|
||||
final ManagedBeanRegistry beans = sessionFactory.getServiceRegistry().getService( ManagedBeanRegistry.class );
|
||||
final ManagedBean<? extends AttributeConverter<?, C>> bean = beans.getBean( converterJavaType );
|
||||
final AttributeConverter<?, C> converter = bean.getBeanInstance();
|
||||
|
||||
return new ConvertedResultBuilder( columnAlias, relationJtd, converter );
|
||||
}
|
||||
|
||||
private final String columnAlias;
|
||||
private final JavaTypeDescriptor<?> relationJtd;
|
||||
private final AttributeConverter<?,?> converter;
|
||||
|
||||
public ConvertedResultBuilder(
|
||||
String columnAlias,
|
||||
JavaTypeDescriptor<?> relationJtd,
|
||||
AttributeConverter<?, ?> converter) {
|
||||
assert columnAlias != null;
|
||||
this.columnAlias = columnAlias;
|
||||
|
||||
assert relationJtd != null;
|
||||
this.relationJtd = relationJtd;
|
||||
|
||||
assert converter != null;
|
||||
this.converter = converter;
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public DomainResult<?> buildReturn(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
|
||||
final int valuesArrayPosition = jdbcPosition - 1;
|
||||
|
||||
final SqlTypeDescriptor std = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
|
||||
final ConverterMapping<Object> converterMapping = new ConverterMapping(
|
||||
relationJtd,
|
||||
std,
|
||||
new ConvertedValueExtractor( std.getExtractor( relationJtd ), converter )
|
||||
);
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, converterMapping );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
|
||||
return new BasicResult( valuesArrayPosition, columnAlias, converterMapping.getJavaTypeDescriptor() );
|
||||
}
|
||||
|
||||
|
||||
private static class ConverterMapping<T> implements MappingModelExpressable<T>, JdbcMapping {
|
||||
private final JavaTypeDescriptor<T> jtd;
|
||||
private final SqlTypeDescriptor std;
|
||||
|
||||
private final ValueExtractor<T> extractor;
|
||||
|
||||
public ConverterMapping(
|
||||
JavaTypeDescriptor<T> jtd,
|
||||
SqlTypeDescriptor std,
|
||||
ValueExtractor<T> extractor) {
|
||||
this.jtd = jtd;
|
||||
this.std = std;
|
||||
this.extractor = extractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCount(TypeConfiguration typeConfiguration) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<T> getJavaTypeDescriptor() {
|
||||
return jtd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlTypeDescriptor getSqlTypeDescriptor() {
|
||||
return std;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueExtractor<T> getJdbcValueExtractor() {
|
||||
return extractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueBinder<?> getJdbcValueBinder() {
|
||||
// this will never get used for binding values
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JdbcMapping> getJdbcMappings(TypeConfiguration typeConfiguration) {
|
||||
return Collections.singletonList( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJdbcTypes(
|
||||
Consumer<JdbcMapping> action,
|
||||
Clause clause,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
action.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class SqlSelectionImpl implements SqlSelection {
|
||||
private final int valuesArrayPosition;
|
||||
private final ConverterMapping converterMapping;
|
||||
|
||||
public SqlSelectionImpl(
|
||||
int valuesArrayPosition,
|
||||
ConverterMapping converterMapping) {
|
||||
this.valuesArrayPosition = valuesArrayPosition;
|
||||
this.converterMapping = converterMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getValuesArrayPosition() {
|
||||
return valuesArrayPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueExtractor getJdbcValueExtractor() {
|
||||
return converterMapping.getJdbcValueExtractor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressable getExpressionType() {
|
||||
return converterMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker sqlAstWalker) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DomainResultCreationStateImpl implements DomainResultCreationState {
|
||||
private final List<ResultBuilder> resultBuilders;
|
||||
private final Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders;
|
||||
private final SqlAstCreationStateImpl sqlAstCreationState;
|
||||
private final FromClauseAccessImpl fromClauseAccess;
|
||||
|
||||
private final LegacyFetchResolverImpl legacyFetchResolver;
|
||||
|
||||
public DomainResultCreationStateImpl(
|
||||
List<ResultBuilder> resultBuilders,
|
||||
Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
this.resultBuilders = resultBuilders;
|
||||
this.legacyFetchBuilders = legacyFetchBuilders;
|
||||
this.fromClauseAccess = new FromClauseAccessImpl();
|
||||
this.sqlAstCreationState = new SqlAstCreationStateImpl( fromClauseAccess, sessionFactory );
|
||||
|
||||
this.legacyFetchResolver = new LegacyFetchResolverImpl();
|
||||
}
|
||||
|
||||
public FromClauseAccessImpl getFromClauseAccess() {
|
||||
return fromClauseAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstCreationStateImpl getSqlAstCreationState() {
|
||||
return sqlAstCreationState;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface LegacyFetchResolver {
|
||||
DynamicFetchBuilderLegacy resolve(String ownerTableAlias, String fetchedPartPath);
|
||||
}
|
||||
|
||||
private static class LegacyFetchResolverImpl implements LegacyFetchResolver {
|
||||
private final Map<String,Map<String, DynamicFetchBuilderLegacy>> legacyFetchResolvers;
|
||||
|
||||
public LegacyFetchResolverImpl() {
|
||||
this.legacyFetchResolvers = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicFetchBuilderLegacy resolve(String ownerTableAlias, String fetchedPartPath) {
|
||||
final Map<String, DynamicFetchBuilderLegacy> fetchBuilders = legacyFetchResolvers.get( ownerTableAlias );
|
||||
if ( fetchBuilders == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fetchBuilders.get( fetchedPartPath );
|
||||
}
|
||||
}
|
||||
|
||||
public LegacyFetchResolver getLegacyFetchResolver() {
|
||||
return legacyFetchResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> visitFetches(FetchParent fetchParent) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
@ -1,63 +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.results;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityResultBuilder
|
||||
extends AbstractPropertyContainer<EntityResultBuilder>
|
||||
implements ResultBuilder, NativeQuery.RootReturn {
|
||||
private final String entityName;
|
||||
private final String tableAlias;
|
||||
|
||||
private LockMode lockMode;
|
||||
|
||||
private String discriminatorColumnAlias;
|
||||
|
||||
public EntityResultBuilder(String entityName, String tableAlias) {
|
||||
this.entityName = entityName;
|
||||
this.tableAlias = tableAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPropertyBase() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildReturn(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResultBuilder setLockMode(LockMode lockMode) {
|
||||
this.lockMode = lockMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResultBuilder setDiscriminatorAlias(String columnAlias) {
|
||||
this.discriminatorColumnAlias = columnAlias;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -6,13 +6,15 @@
|
||||
*/
|
||||
package org.hibernate.query.results;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
@ -21,13 +23,16 @@
|
||||
* Responsible for building a single {@link DomainResult} instance as part of
|
||||
* the overall mapping of native / procedure query results.
|
||||
*
|
||||
* @apiNote By definition a fetch is a reference to the fetched ModelPart
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Incubating
|
||||
public interface FetchBuilder extends NativeQuery.ReturnProperty {
|
||||
public interface FetchBuilder {
|
||||
|
||||
Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
NavigablePath fetchPath, JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory);
|
||||
DomainResultCreationState domainResultCreationState);
|
||||
}
|
||||
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class FromClauseAccessImpl implements FromClauseAccess {
|
||||
private List<TableGroup> rootTableGroups;
|
||||
private Map<String, TableGroup> tableGroupBySqlAlias;
|
||||
private Map<NavigablePath, TableGroup> tableGroupByPath;
|
||||
|
||||
public FromClauseAccessImpl() {
|
||||
}
|
||||
|
||||
public List<TableGroup> getRootTableGroups() {
|
||||
return rootTableGroups;
|
||||
}
|
||||
|
||||
public TableGroup getByAlias(String alias) {
|
||||
final TableGroup byAlias = findByAlias( alias );
|
||||
if ( byAlias == null ) {
|
||||
throw new IllegalArgumentException( "Could not resolve TableGroup by alias [" + alias + "]" );
|
||||
}
|
||||
return byAlias;
|
||||
}
|
||||
|
||||
public TableGroup findByAlias(String alias) {
|
||||
if ( tableGroupBySqlAlias != null ) {
|
||||
final TableGroup tableGroup = tableGroupBySqlAlias.get( alias );
|
||||
if ( tableGroup != null ) {
|
||||
return tableGroup;
|
||||
}
|
||||
}
|
||||
|
||||
if ( rootTableGroups != null && rootTableGroups.size() == 1 ) {
|
||||
return rootTableGroups.get( 0 );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup findTableGroup(NavigablePath navigablePath) {
|
||||
if ( tableGroupByPath != null ) {
|
||||
final TableGroup tableGroup = tableGroupByPath.get( navigablePath );
|
||||
if ( tableGroup != null ) {
|
||||
return tableGroup;
|
||||
}
|
||||
}
|
||||
|
||||
if ( rootTableGroups != null && rootTableGroups.size() == 1 ) {
|
||||
return rootTableGroups.get( 0 );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTableGroup(NavigablePath navigablePath, TableGroup tableGroup) {
|
||||
if ( tableGroupByPath == null ) {
|
||||
tableGroupByPath = new HashMap<>();
|
||||
}
|
||||
tableGroupByPath.put( navigablePath, tableGroup );
|
||||
|
||||
if ( tableGroup.getGroupAlias() != null ) {
|
||||
if ( tableGroupBySqlAlias == null ) {
|
||||
tableGroupBySqlAlias = new HashMap<>();
|
||||
}
|
||||
tableGroupBySqlAlias.put( tableGroup.getGroupAlias(), tableGroup );
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +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.results;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface PropertyContainer {
|
||||
/**
|
||||
* Add a simple property-to-one-column mapping.
|
||||
*/
|
||||
PropertyContainer addProperty(String propertyName, String columnAlias);
|
||||
|
||||
/**
|
||||
* Add a property mapped to multiple columns
|
||||
*/
|
||||
PropertyContainer addProperty(String propertyName, String... columnAliases);
|
||||
|
||||
/**
|
||||
* Add a property whose columns can later be defined using {@link FetchBuilder#addColumnAlias}
|
||||
*/
|
||||
FetchBuilder addProperty(String propertyName);
|
||||
}
|
@ -10,9 +10,10 @@
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
@ -23,9 +24,10 @@
|
||||
*/
|
||||
@Incubating
|
||||
public interface ResultBuilder {
|
||||
DomainResult<?> buildReturn(
|
||||
DomainResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String,String,LegacyFetchBuilder> legacyFetchResolver,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory);
|
||||
DomainResultCreationState domainResultCreationState);
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* Nominal extension to ResultBuilder for cases involving scalar results
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ResultBuilderBasicValued extends ResultBuilder {
|
||||
@Override
|
||||
BasicResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState);
|
||||
}
|
@ -6,30 +6,26 @@
|
||||
*/
|
||||
package org.hibernate.query.results;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* Specialization of ResultBuilder for building an EntityResult
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardFetchBuilderImpl implements FetchBuilder {
|
||||
public interface ResultBuilderEntityValued extends ResultBuilder {
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQuery.ReturnProperty addColumnAlias(String columnAlias) {
|
||||
return null;
|
||||
}
|
||||
DomainResultCreationState domainResultCreationState);
|
||||
}
|
@ -11,5 +11,5 @@
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface InstantiationResultBuilder extends ResultBuilder {
|
||||
public interface ResultBuilderInstantiationValued extends ResultBuilder {
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
||||
|
||||
/**
|
||||
@ -17,13 +18,20 @@
|
||||
* or {@link org.hibernate.procedure.ProcedureCall} / {@link javax.persistence.StoredProcedureQuery}
|
||||
* instances.
|
||||
*
|
||||
* Collects builders for results and fetches and manages resolving them via JdbcValuesMappingProducer
|
||||
*
|
||||
* @see org.hibernate.query.NativeQuery#addScalar
|
||||
* @see org.hibernate.query.NativeQuery#addEntity
|
||||
* @see org.hibernate.query.NativeQuery#addJoin
|
||||
* @see org.hibernate.query.NativeQuery#addFetch
|
||||
* @see org.hibernate.query.NativeQuery#addRoot
|
||||
* Can be defined<ul>
|
||||
* <li>
|
||||
* statically via {@link javax.persistence.SqlResultSetMapping} or `hbm.xml` mapping
|
||||
* </li>
|
||||
* <li>
|
||||
* dynamically via Hibernate-specific APIs:<ul>
|
||||
* <li>{@link org.hibernate.query.NativeQuery#addScalar}</li>
|
||||
* <li>{@link org.hibernate.query.NativeQuery#addEntity}</li>
|
||||
* <li>{@link org.hibernate.query.NativeQuery#addJoin}</li>
|
||||
* <li>{@link org.hibernate.query.NativeQuery#addFetch}</li>
|
||||
* <li>{@link org.hibernate.query.NativeQuery#addRoot}</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@ -34,7 +42,7 @@ public interface ResultSetMapping extends JdbcValuesMappingProducer {
|
||||
void visitResultBuilders(BiConsumer<Integer, ResultBuilder> resultBuilderConsumer);
|
||||
|
||||
void addResultBuilder(ResultBuilder resultBuilder);
|
||||
void addLegacyFetchBuilder(LegacyFetchBuilder fetchBuilder);
|
||||
void addLegacyFetchBuilder(DynamicFetchBuilderLegacy fetchBuilder);
|
||||
|
||||
NamedResultSetMappingMemento toMemento(String name);
|
||||
}
|
||||
|
@ -17,7 +17,9 @@
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
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.basic.BasicResult;
|
||||
@ -35,7 +37,7 @@
|
||||
@Internal
|
||||
public class ResultSetMappingImpl implements ResultSetMapping {
|
||||
private List<ResultBuilder> resultBuilders;
|
||||
private Map<String, Map<String,LegacyFetchBuilder>> legacyFetchBuilders;
|
||||
private Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders;
|
||||
|
||||
@Override
|
||||
public int getNumberOfResultBuilders() {
|
||||
@ -62,8 +64,8 @@ public void addResultBuilder(ResultBuilder resultBuilder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLegacyFetchBuilder(LegacyFetchBuilder fetchBuilder) {
|
||||
final Map<String, LegacyFetchBuilder> existingFetchBuildersByOwner;
|
||||
public void addLegacyFetchBuilder(DynamicFetchBuilderLegacy fetchBuilder) {
|
||||
final Map<String, DynamicFetchBuilderLegacy> existingFetchBuildersByOwner;
|
||||
|
||||
if ( legacyFetchBuilders == null ) {
|
||||
legacyFetchBuilders = new HashMap<>();
|
||||
@ -73,7 +75,7 @@ public void addLegacyFetchBuilder(LegacyFetchBuilder fetchBuilder) {
|
||||
existingFetchBuildersByOwner = legacyFetchBuilders.get( fetchBuilder.getOwnerAlias() );
|
||||
}
|
||||
|
||||
final Map<String, LegacyFetchBuilder> fetchBuildersByOwner;
|
||||
final Map<String, DynamicFetchBuilderLegacy> fetchBuildersByOwner;
|
||||
if ( existingFetchBuildersByOwner == null ) {
|
||||
fetchBuildersByOwner = new HashMap<>();
|
||||
legacyFetchBuilders.put( fetchBuilder.getOwnerAlias(), fetchBuildersByOwner );
|
||||
@ -82,7 +84,7 @@ public void addLegacyFetchBuilder(LegacyFetchBuilder fetchBuilder) {
|
||||
fetchBuildersByOwner = existingFetchBuildersByOwner;
|
||||
}
|
||||
|
||||
final LegacyFetchBuilder previousBuilder = fetchBuildersByOwner.put( fetchBuilder.getFetchedAttributeName(), fetchBuilder );
|
||||
final DynamicFetchBuilderLegacy previousBuilder = fetchBuildersByOwner.put( fetchBuilder.getFetchableName(), fetchBuilder );
|
||||
if ( previousBuilder != null ) {
|
||||
// todo (6.0) : error? log? nothing?
|
||||
}
|
||||
@ -92,7 +94,6 @@ public void addLegacyFetchBuilder(LegacyFetchBuilder fetchBuilder) {
|
||||
public JdbcValuesMapping resolve(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final List<SqlSelection> sqlSelections = new ArrayList<>( jdbcResultsMetadata.getColumnCount() );
|
||||
|
||||
final int numberOfResults;
|
||||
|
||||
@ -103,8 +104,15 @@ public JdbcValuesMapping resolve(
|
||||
numberOfResults = resultBuilders.size();
|
||||
}
|
||||
|
||||
final List<SqlSelection> sqlSelections = new ArrayList<>( jdbcResultsMetadata.getColumnCount() );
|
||||
final List<DomainResult<?>> domainResults = new ArrayList<>( numberOfResults );
|
||||
|
||||
final DomainResultCreationStateImpl creationState = new DomainResultCreationStateImpl(
|
||||
resultBuilders,
|
||||
legacyFetchBuilders,
|
||||
sessionFactory
|
||||
);
|
||||
|
||||
for ( int i = 0; i < numberOfResults; i++ ) {
|
||||
final ResultBuilder resultBuilder = resultBuilders != null
|
||||
? resultBuilders.get( i )
|
||||
@ -120,23 +128,23 @@ public JdbcValuesMapping resolve(
|
||||
);
|
||||
}
|
||||
else {
|
||||
domainResult = resultBuilder.buildReturn(
|
||||
domainResult = resultBuilder.buildResult(
|
||||
jdbcResultsMetadata,
|
||||
(ownerAlias, fetchName) -> {
|
||||
domainResults.size(),
|
||||
(entityName, fetchableName) -> {
|
||||
if ( legacyFetchBuilders == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Map<String, LegacyFetchBuilder> fetchBuildersForOwner = legacyFetchBuilders.get(
|
||||
ownerAlias );
|
||||
if ( fetchBuildersForOwner == null ) {
|
||||
final Map<String, DynamicFetchBuilderLegacy> fetchBuilderMap = legacyFetchBuilders.get( entityName );
|
||||
if ( fetchBuilderMap == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fetchBuildersForOwner.get( fetchName );
|
||||
return fetchBuilderMap.get( fetchableName );
|
||||
},
|
||||
sqlSelections::add,
|
||||
sessionFactory
|
||||
creationState
|
||||
);
|
||||
}
|
||||
domainResults.add( domainResult );
|
||||
@ -164,7 +172,7 @@ private DomainResult<?> makeImplicitDomainResult(
|
||||
|
||||
final String name = jdbcResultsMetadata.resolveColumnName( jdbcPosition );
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, jdbcMapping );
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) jdbcMapping );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
|
||||
return new BasicResult( valuesArrayPosition, name, jdbcMapping.getJavaTypeDescriptor() );
|
||||
|
@ -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.results;
|
||||
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ResultsHelper {
|
||||
public static int jdbcPositionToValuesArrayPosition(int jdbcPosition) {
|
||||
return jdbcPosition - 1;
|
||||
}
|
||||
|
||||
public static int valuesArrayPositionToJdbcPosition(int valuesArrayPosition) {
|
||||
return valuesArrayPosition + 1;
|
||||
}
|
||||
|
||||
public static DomainResultCreationStateImpl impl(DomainResultCreationState 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) {
|
||||
if ( creationState instanceof DomainResultCreationStateImpl ) {
|
||||
return ( (DomainResultCreationStateImpl) creationState );
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"Passed DomainResultCreationState not an instance of org.hibernate.query.results.DomainResultCreationStateImpl"
|
||||
);
|
||||
}
|
||||
|
||||
private ResultsHelper() {
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.LockMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
|
||||
/**
|
||||
* SqlAstCreationState implementation for result-set mapping handling
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqlAstCreationStateImpl implements SqlAstCreationState {
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private final FromClauseAccessImpl fromClauseAccess;
|
||||
private final SqlAstProcessingStateImpl processingState;
|
||||
|
||||
public SqlAstCreationStateImpl(
|
||||
FromClauseAccessImpl fromClauseAccess,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.fromClauseAccess = fromClauseAccess;
|
||||
this.processingState = new SqlAstProcessingStateImpl( this, fromClauseAccess );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstCreationContext getCreationContext() {
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstProcessingStateImpl getCurrentProcessingState() {
|
||||
return processingState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstProcessingStateImpl getSqlExpressionResolver() {
|
||||
return processingState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromClauseAccessImpl getFromClauseAccess() {
|
||||
return fromClauseAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAliasBaseGenerator getSqlAliasBaseGenerator() {
|
||||
return stem -> {
|
||||
throw new UnsupportedOperationException();
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockMode determineLockMode(String identificationVariable) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -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.results;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
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.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqlAstProcessingStateImpl implements SqlAstProcessingState, SqlExpressionResolver {
|
||||
private final SqlAstCreationState sqlAstCreationState;
|
||||
private final FromClauseAccessImpl fromClauseAccess;
|
||||
|
||||
private final Map<String,SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
|
||||
|
||||
public SqlAstProcessingStateImpl(
|
||||
SqlAstCreationState sqlAstCreationState,
|
||||
FromClauseAccessImpl fromClauseAccess) {
|
||||
this.sqlAstCreationState = sqlAstCreationState;
|
||||
this.fromClauseAccess = fromClauseAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstProcessingState getParentState() {
|
||||
// none
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlExpressionResolver getSqlExpressionResolver() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstCreationState getSqlAstCreationState() {
|
||||
return sqlAstCreationState;
|
||||
}
|
||||
|
||||
public int getNumberOfProcessedSelections() {
|
||||
return sqlSelectionMap.size();
|
||||
}
|
||||
|
||||
@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 );
|
||||
}
|
||||
else if ( created instanceof ColumnReference ) {
|
||||
final ColumnReference columnReference = (ColumnReference) created;
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl(
|
||||
sqlSelectionMap.size() + 1,
|
||||
columnReference.getJdbcMapping()
|
||||
);
|
||||
sqlSelectionMap.put( key, sqlSelection );
|
||||
}
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlSelection resolveSqlSelection(
|
||||
Expression expression,
|
||||
JavaTypeDescriptor javaTypeDescriptor,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
assert expression instanceof SqlSelectionImpl;
|
||||
return (SqlSelection) expression;
|
||||
}
|
||||
|
||||
public FromClauseAccess getFromClauseAccess() {
|
||||
return fromClauseAccess;
|
||||
}
|
||||
}
|
@ -7,28 +7,51 @@
|
||||
package org.hibernate.query.results;
|
||||
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* SqlSelection for NativeQuery
|
||||
* SqlSelection used in {@link ResultSetMapping} resolution. Doubles as its own
|
||||
* {@link Expression} as well.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqlSelectionImpl implements SqlSelection {
|
||||
public class SqlSelectionImpl implements SqlSelection, Expression {
|
||||
private final int valuesArrayPosition;
|
||||
private final BasicValuedMapping valueMapping;
|
||||
private final JdbcMapping jdbcMapping;
|
||||
|
||||
public SqlSelectionImpl(int valuesArrayPosition, BasicValuedMapping valueMapping) {
|
||||
this.valuesArrayPosition = valuesArrayPosition;
|
||||
this.valueMapping = valueMapping;
|
||||
this.jdbcMapping = valueMapping.getJdbcMapping();
|
||||
}
|
||||
|
||||
public SqlSelectionImpl(int valuesArrayPosition, JdbcMapping jdbcMapping) {
|
||||
this.valuesArrayPosition = valuesArrayPosition;
|
||||
this.jdbcMapping = jdbcMapping;
|
||||
|
||||
this.valueMapping = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueExtractor getJdbcValueExtractor() {
|
||||
return valueMapping.getJdbcMapping().getJdbcValueExtractor();
|
||||
return jdbcMapping.getJdbcValueExtractor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlSelection createSqlSelection(
|
||||
int jdbcPosition,
|
||||
int valuesArrayPosition,
|
||||
JavaTypeDescriptor javaTypeDescriptor,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,109 +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.results;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* @see javax.persistence.ColumnResult
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardScalarResultBuilder implements ScalarResultBuilder {
|
||||
private final String explicitName;
|
||||
|
||||
private final BasicType<?> explicitType;
|
||||
private final JavaTypeDescriptor<?> explicitJavaTypeDescriptor;
|
||||
|
||||
public StandardScalarResultBuilder(String explicitName) {
|
||||
assert explicitName != null;
|
||||
this.explicitName = explicitName;
|
||||
|
||||
this.explicitType = null;
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
public StandardScalarResultBuilder(String explicitName, BasicType<?> explicitType) {
|
||||
assert explicitName != null;
|
||||
this.explicitName = explicitName;
|
||||
|
||||
assert explicitType != null;
|
||||
this.explicitType = explicitType;
|
||||
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
public StandardScalarResultBuilder(String explicitName, JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
|
||||
assert explicitName != null;
|
||||
this.explicitName = explicitName;
|
||||
|
||||
assert explicitJavaTypeDescriptor != null;
|
||||
this.explicitJavaTypeDescriptor = explicitJavaTypeDescriptor;
|
||||
|
||||
this.explicitType = null;
|
||||
}
|
||||
|
||||
StandardScalarResultBuilder(JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
|
||||
assert explicitJavaTypeDescriptor != null;
|
||||
this.explicitJavaTypeDescriptor = explicitJavaTypeDescriptor;
|
||||
|
||||
this.explicitName = null;
|
||||
this.explicitType = null;
|
||||
}
|
||||
|
||||
public String getExplicitName() {
|
||||
return explicitName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildReturn(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( explicitName );
|
||||
final int valuesArrayPosition = jdbcPosition - 1;
|
||||
|
||||
final BasicType<?> jdbcMapping;
|
||||
|
||||
if ( explicitType != null ) {
|
||||
jdbcMapping = explicitType;
|
||||
}
|
||||
else if ( explicitJavaTypeDescriptor != null ) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
|
||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( explicitJavaTypeDescriptor, sqlTypeDescriptor );
|
||||
}
|
||||
else {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
final JavaTypeDescriptor<?> javaTypeDescriptor = sqlTypeDescriptor.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
|
||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
|
||||
}
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, jdbcMapping );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
|
||||
return new BasicResult( valuesArrayPosition, explicitName, jdbcMapping.getJavaTypeDescriptor() );
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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 java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||
|
||||
/**
|
||||
* A TableGroup created with regards to a SQL ResultSet mapping
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TableGroupImpl implements TableGroup {
|
||||
private final NavigablePath navigablePath;
|
||||
private final String alias;
|
||||
|
||||
private final TableReferenceImpl primaryTableReference;
|
||||
|
||||
private final ModelPartContainer container;
|
||||
private final LockMode lockMode;
|
||||
|
||||
private Set<TableGroupJoin> tableGroupJoins;
|
||||
|
||||
public TableGroupImpl(
|
||||
NavigablePath navigablePath,
|
||||
String alias,
|
||||
TableReferenceImpl primaryTableReference,
|
||||
ModelPartContainer container,
|
||||
LockMode lockMode) {
|
||||
this.navigablePath = navigablePath;
|
||||
this.alias = alias;
|
||||
this.primaryTableReference = primaryTableReference;
|
||||
this.container = container;
|
||||
this.lockMode = lockMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return navigablePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupAlias() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPartContainer getModelPart() {
|
||||
return container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPartContainer getExpressionType() {
|
||||
return getModelPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockMode getLockMode() {
|
||||
return lockMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TableGroupJoin> getTableGroupJoins() {
|
||||
return tableGroupJoins == null ? Collections.emptySet() : tableGroupJoins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTableGroupJoins() {
|
||||
return tableGroupJoins != null && ! tableGroupJoins.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTableGroupJoins(Set<TableGroupJoin> joins) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTableGroupJoin(TableGroupJoin join) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||
if ( tableGroupJoins == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
tableGroupJoins.forEach( consumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference getPrimaryTableReference() {
|
||||
return primaryTableReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TableReferenceJoin> getTableReferenceJoins() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInnerJoinPossible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(
|
||||
String tableExpression, Supplier<TableReference> creator) {
|
||||
return primaryTableReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression) {
|
||||
return primaryTableReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
return primaryTableReference;
|
||||
}
|
||||
|
||||
public static class TableReferenceImpl extends TableReference {
|
||||
public TableReferenceImpl(
|
||||
String tableExpression,
|
||||
String identificationVariable,
|
||||
boolean isOptional,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
super( tableExpression, identificationVariable, isOptional, sessionFactory );
|
||||
}
|
||||
}
|
||||
}
|
@ -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.complete;
|
||||
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CompleteFetchBuilder extends FetchBuilder, ModelPartReference {
|
||||
@Override
|
||||
Fetchable getReferencedPart();
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FromClauseAccessImpl;
|
||||
import org.hibernate.query.results.SqlAstCreationStateImpl;
|
||||
import org.hibernate.query.results.SqlAstProcessingStateImpl;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
import static org.hibernate.query.results.ResultsHelper.impl;
|
||||
import static org.hibernate.query.results.ResultsHelper.jdbcPositionToValuesArrayPosition;
|
||||
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder {
|
||||
private final BasicValuedModelPart referencedModelPart;
|
||||
private final String columnName;
|
||||
|
||||
public CompleteFetchBuilderBasicPart(BasicValuedModelPart referencedModelPart, String columnName) {
|
||||
this.referencedModelPart = referencedModelPart;
|
||||
this.columnName = columnName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicValuedModelPart getReferencedPart() {
|
||||
return referencedModelPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
NavigablePath fetchPath,
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
final DomainResultCreationStateImpl domainResultCreationStateImpl = impl( domainResultCreationState );
|
||||
final SqlAstCreationStateImpl sqlAstCreationState = domainResultCreationStateImpl.getSqlAstCreationState();
|
||||
final FromClauseAccessImpl fromClauseAccess = domainResultCreationStateImpl.getFromClauseAccess();
|
||||
final SqlAstProcessingStateImpl sqlAstProcessingState = sqlAstCreationState.getCurrentProcessingState();
|
||||
|
||||
final String mappedTable = referencedModelPart.getContainingTableExpression();
|
||||
final String mappedColumn = referencedModelPart.getMappedColumnExpression();
|
||||
|
||||
final TableGroup tableGroup = fromClauseAccess.getTableGroup( parent.getNavigablePath() );
|
||||
final TableReference tableReference = tableGroup.getTableReference( mappedTable );
|
||||
|
||||
final String selectedAlias;
|
||||
final int jdbcPosition;
|
||||
|
||||
if ( columnName == null ) {
|
||||
jdbcPosition = sqlAstProcessingState.getNumberOfProcessedSelections();
|
||||
selectedAlias = jdbcResultsMetadata.resolveColumnName( jdbcPosition );
|
||||
}
|
||||
else {
|
||||
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnName );
|
||||
selectedAlias = columnName;
|
||||
}
|
||||
|
||||
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
|
||||
|
||||
// we just care about the registration here. The ModelPart will find it later
|
||||
|
||||
sqlAstProcessingState.resolveSqlExpression(
|
||||
createColumnReferenceKey( tableReference, mappedColumn ),
|
||||
processingState -> new SqlSelectionImpl( valuesArrayPosition, referencedModelPart )
|
||||
);
|
||||
// final Expression expression = sqlAstProcessingState.resolveSqlExpression(
|
||||
// createColumnReferenceKey( tableReference, mappedColumn ),
|
||||
// processingState -> new SqlSelectionImpl( valuesArrayPosition, referencedModelPart )
|
||||
// );
|
||||
//
|
||||
// final SqlSelection sqlSelection = sqlAstProcessingState.resolveSqlSelection(
|
||||
// expression,
|
||||
// referencedModelPart.getJavaTypeDescriptor(),
|
||||
// sqlAstCreationState.getCreationContext().getSessionFactory().getTypeConfiguration()
|
||||
// );
|
||||
|
||||
return referencedModelPart.generateFetch(
|
||||
parent,
|
||||
fetchPath,
|
||||
FetchTiming.IMMEDIATE,
|
||||
true,
|
||||
LockMode.READ,
|
||||
selectedAlias,
|
||||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
}
|
@ -4,10 +4,12 @@
|
||||
* 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;
|
||||
package org.hibernate.query.results.complete;
|
||||
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface BuilderGraphNode {
|
||||
public interface CompleteResultBuilder extends ResultBuilder {
|
||||
}
|
@ -4,12 +4,14 @@
|
||||
* 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;
|
||||
package org.hibernate.query.results.complete;
|
||||
|
||||
import org.hibernate.query.results.ResultBuilderBasicValued;
|
||||
|
||||
/**
|
||||
* Nominal extension to ResultBuilder for cases involving scalar results
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ScalarResultBuilder extends ResultBuilder {
|
||||
public interface CompleteResultBuilderBasicValued extends CompleteResultBuilder, ResultBuilderBasicValued {
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||
import org.hibernate.query.internal.ScalarResultMappingMemento;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* ResultBuilder for scalar results defined via:<ul>
|
||||
* <li>JPA {@link javax.persistence.ColumnResult}</li>
|
||||
* <li>`<return-scalar/>` as part of a `<resultset/>` stanza in `hbm.xml`</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CompleteResultBuilderBasicValuedStandard implements CompleteResultBuilderBasicValued {
|
||||
|
||||
private final String explicitColumnName;
|
||||
|
||||
private final BasicType<?> explicitType;
|
||||
private final JavaTypeDescriptor<?> explicitJavaTypeDescriptor;
|
||||
|
||||
public CompleteResultBuilderBasicValuedStandard(
|
||||
ScalarResultMappingMemento memento,
|
||||
ResultSetMappingResolutionContext context) {
|
||||
this.explicitColumnName = memento.getExplicitColumnName();
|
||||
this.explicitType = memento.getExplicitType();
|
||||
this.explicitJavaTypeDescriptor = memento.getExplicitJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
final SessionFactoryImplementor sessionFactory = domainResultCreationState.getSqlAstCreationState()
|
||||
.getCreationContext()
|
||||
.getSessionFactory();
|
||||
|
||||
final int jdbcPosition;
|
||||
final String columnName;
|
||||
|
||||
if ( explicitColumnName != null ) {
|
||||
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( explicitColumnName );
|
||||
columnName = explicitColumnName;
|
||||
}
|
||||
else {
|
||||
jdbcPosition = resultPosition + 1;
|
||||
columnName = jdbcResultsMetadata.resolveColumnName( jdbcPosition );
|
||||
}
|
||||
|
||||
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
|
||||
|
||||
final BasicType<?> basicType;
|
||||
|
||||
if ( explicitType != null ) {
|
||||
basicType = explicitType;
|
||||
}
|
||||
else if ( explicitJavaTypeDescriptor != null ) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
|
||||
basicType = typeConfiguration.getBasicTypeRegistry().resolve( explicitJavaTypeDescriptor, sqlTypeDescriptor );
|
||||
}
|
||||
else {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
final JavaTypeDescriptor<?> javaTypeDescriptor = sqlTypeDescriptor.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
|
||||
basicType = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
|
||||
}
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
|
||||
return new BasicResult<>( valuesArrayPosition, columnName, basicType.getJavaTypeDescriptor() );
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.EntityMappingType;
|
||||
import org.hibernate.query.results.ResultBuilderEntityValued;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CompleteResultBuilderEntityValued
|
||||
extends CompleteResultBuilder, ModelPartReference, ResultBuilderEntityValued {
|
||||
@Override
|
||||
EntityMappingType getReferencedPart();
|
||||
}
|
@ -4,30 +4,37 @@
|
||||
* 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;
|
||||
package org.hibernate.query.results.complete;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.DynamicInstantiationNature;
|
||||
import org.hibernate.query.results.ResultBuilderInstantiationValued;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.instantiation.internal.ArgumentDomainResult;
|
||||
import org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiationResultImpl;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* ResultBuilder for dynamic instantiation results ({@link javax.persistence.ConstructorResult}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardInstantiationResultBuilder implements InstantiationResultBuilder {
|
||||
public class CompleteResultBuilderInstantiation
|
||||
implements CompleteResultBuilder, ResultBuilderInstantiationValued {
|
||||
|
||||
private final JavaTypeDescriptor<?> javaTypeDescriptor;
|
||||
private final List<ResultBuilder> argumentResultBuilders;
|
||||
|
||||
public StandardInstantiationResultBuilder(
|
||||
public CompleteResultBuilderInstantiation(
|
||||
JavaTypeDescriptor<?> javaTypeDescriptor,
|
||||
List<ResultBuilder> argumentResultBuilders) {
|
||||
this.javaTypeDescriptor = javaTypeDescriptor;
|
||||
@ -35,22 +42,30 @@ public StandardInstantiationResultBuilder(
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildReturn(
|
||||
public DomainResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
final List<ArgumentDomainResult<?>> argumentDomainResults = new ArrayList<>( argumentResultBuilders.size() );
|
||||
|
||||
argumentResultBuilders.forEach(
|
||||
argumentResultBuilder -> argumentDomainResults.add(
|
||||
new ArgumentDomainResult<>(
|
||||
argumentResultBuilder.buildReturn( jdbcResultsMetadata, legacyFetchResolver, sqlSelectionConsumer, sessionFactory )
|
||||
)
|
||||
)
|
||||
);
|
||||
for ( int i = 0; i < argumentResultBuilders.size(); i++ ) {
|
||||
final ResultBuilder argumentResultBuilder = argumentResultBuilders.get( i );
|
||||
|
||||
final ArgumentDomainResult<Object> argumentDomainResult = new ArgumentDomainResult<>(
|
||||
argumentResultBuilder.buildResult(
|
||||
jdbcResultsMetadata,
|
||||
i,
|
||||
legacyFetchResolver,
|
||||
sqlSelectionConsumer,
|
||||
domainResultCreationState
|
||||
)
|
||||
);
|
||||
|
||||
argumentDomainResults.add( argumentDomainResult );
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return new DynamicInstantiationResultImpl(
|
||||
null,
|
||||
DynamicInstantiationNature.CLASS,
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.ModelPart;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
|
||||
/**
|
||||
* A {@link ResultBuilder} or {@link FetchBuilder} that refers to some part
|
||||
* of the user's domain model
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ModelPartReference {
|
||||
/**
|
||||
* The part of the domain model that is referenced
|
||||
*/
|
||||
ModelPart getReferencedPart();
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for immutable result/fetch builder graph nodes built from static sources
|
||||
* such as JPA's {@link javax.persistence.SqlResultSetMapping} or `hbm.xml` mapping
|
||||
* `<resultset/>`.
|
||||
*
|
||||
* The differentiation from {@link org.hibernate.query.results.dynamic} is that here
|
||||
* we have up-front knowledge of the complete mapping graph and can perform optimized
|
||||
* resolution process
|
||||
*/
|
||||
package org.hibernate.query.results.complete;
|
@ -4,25 +4,32 @@
|
||||
* 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;
|
||||
package org.hibernate.query.results.dynamic;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractPropertyContainer<T extends AbstractPropertyContainer<T>> implements PropertyContainer {
|
||||
private Map<String,FetchBuilder> fetchBuilderMap;
|
||||
public abstract class AbstractFetchBuilderContainer<T extends AbstractFetchBuilderContainer<T>>
|
||||
implements DynamicFetchBuilderContainer {
|
||||
private Map<String, DynamicFetchBuilder> fetchBuilderMap;
|
||||
|
||||
protected abstract String getPropertyBase();
|
||||
|
||||
@Override
|
||||
public DynamicFetchBuilder findFetchBuilder(String fetchableName) {
|
||||
return fetchBuilderMap == null ? null : fetchBuilderMap.get( fetchableName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public T addProperty(String propertyName, String columnAlias) {
|
||||
final FetchBuilder fetchBuilder = addProperty( propertyName );
|
||||
final DynamicFetchBuilder fetchBuilder = addProperty( propertyName );
|
||||
fetchBuilder.addColumnAlias( columnAlias );
|
||||
|
||||
return (T) this;
|
||||
@ -30,14 +37,14 @@ public T addProperty(String propertyName, String columnAlias) {
|
||||
|
||||
@Override
|
||||
public T addProperty(String propertyName, String... columnAliases) {
|
||||
final FetchBuilder fetchBuilder = addProperty( propertyName );
|
||||
final DynamicFetchBuilder fetchBuilder = addProperty( propertyName );
|
||||
ArrayHelper.forEach( columnAliases, fetchBuilder::addColumnAlias );
|
||||
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchBuilder addProperty(String propertyName) {
|
||||
public DynamicFetchBuilder addProperty(String propertyName) {
|
||||
if ( fetchBuilderMap == null ) {
|
||||
fetchBuilderMap = new HashMap<>();
|
||||
}
|
||||
@ -56,7 +63,11 @@ public FetchBuilder addProperty(String propertyName) {
|
||||
}
|
||||
}
|
||||
|
||||
final FetchBuilder fetchBuilder = new StandardFetchBuilderImpl();
|
||||
final DynamicFetchBuilderStandard fetchBuilder = new DynamicFetchBuilderStandard(
|
||||
this,
|
||||
propertyName
|
||||
);
|
||||
|
||||
fetchBuilderMap.put( propertyName, fetchBuilder );
|
||||
|
||||
return fetchBuilder;
|
@ -4,15 +4,14 @@
|
||||
* 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;
|
||||
package org.hibernate.query.results.dynamic;
|
||||
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface LegacyFetchBuilder extends FetchBuilder, NativeQuery.FetchReturn {
|
||||
String getOwnerAlias();
|
||||
String getFetchAlias();
|
||||
String getFetchedAttributeName();
|
||||
public interface DynamicFetchBuilder extends FetchBuilder, NativeQuery.ReturnProperty {
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DynamicFetchBuilderContainer {
|
||||
/**
|
||||
* Locate an explicit fetch definition for the named fetchable
|
||||
*/
|
||||
DynamicFetchBuilder findFetchBuilder(String fetchableName);
|
||||
|
||||
/**
|
||||
* Add a property mapped to a single column.
|
||||
*/
|
||||
DynamicFetchBuilderContainer addProperty(String propertyName, String columnAlias);
|
||||
|
||||
/**
|
||||
* Add a property mapped to multiple columns
|
||||
*/
|
||||
DynamicFetchBuilderContainer addProperty(String propertyName, String... columnAliases);
|
||||
|
||||
/**
|
||||
* Add a property whose columns can later be defined using {@link DynamicFetchBuilder#addColumnAlias}
|
||||
*/
|
||||
DynamicFetchBuilder addProperty(String propertyName);
|
||||
}
|
@ -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.results.dynamic;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.FromClauseAccessImpl;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQuery.FetchReturn {
|
||||
|
||||
private final String tableAlias;
|
||||
|
||||
private final String ownerTableAlias;
|
||||
private final String fetchableName;
|
||||
|
||||
private final List<String> columnNames;
|
||||
|
||||
public DynamicFetchBuilderLegacy(
|
||||
String tableAlias,
|
||||
String ownerTableAlias,
|
||||
String fetchableName,
|
||||
List<String> columnNames) {
|
||||
this.tableAlias = tableAlias;
|
||||
this.ownerTableAlias = ownerTableAlias;
|
||||
this.fetchableName = fetchableName;
|
||||
this.columnNames = columnNames;
|
||||
}
|
||||
|
||||
public String getTableAlias() {
|
||||
return tableAlias;
|
||||
}
|
||||
|
||||
public String getOwnerAlias() {
|
||||
return ownerTableAlias;
|
||||
}
|
||||
|
||||
public String getFetchableName() {
|
||||
return fetchableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
NavigablePath fetchPath,
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
final FromClauseAccessImpl fromClauseAccess = ResultsHelper.extractFromClauseAccess( domainResultCreationState );
|
||||
|
||||
final TableGroup ownerTableGroup = fromClauseAccess.findByAlias( ownerTableAlias );
|
||||
|
||||
// todo (6.0) : create the TableGroupJoin for the fetch and then build the fetch
|
||||
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQuery.ReturnProperty addColumnAlias(String columnAlias) {
|
||||
columnNames.add( columnAlias );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQuery.FetchReturn setLockMode(LockMode lockMode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQuery.FetchReturn addProperty(String propertyName, String columnAlias) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQuery.ReturnProperty addProperty(String propertyName) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.FromClauseAccessImpl;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DynamicFetchBuilderStandard
|
||||
implements DynamicFetchBuilder, NativeQuery.ReturnProperty {
|
||||
|
||||
private final DynamicFetchBuilderContainer container;
|
||||
private final String fetchableName;
|
||||
|
||||
private final List<String> columnNames = new ArrayList<>();
|
||||
|
||||
public DynamicFetchBuilderStandard(
|
||||
DynamicFetchBuilderContainer container,
|
||||
String fetchableName) {
|
||||
this.container = container;
|
||||
this.fetchableName = fetchableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch buildFetch(
|
||||
FetchParent parent,
|
||||
NavigablePath fetchPath,
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
final FromClauseAccessImpl fromClauseAccess = ResultsHelper.extractFromClauseAccess( domainResultCreationState );
|
||||
|
||||
final TableGroup ownerTableGroup = fromClauseAccess.getTableGroup( parent.getNavigablePath() );
|
||||
|
||||
// todo (6.0) : create the TableGroupJoin for the fetch and then build the fetch
|
||||
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQuery.ReturnProperty addColumnAlias(String columnAlias) {
|
||||
columnNames.add( columnAlias );
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
|
||||
/**
|
||||
* ResultBuilder specialization for results added through the Hibernate-specific
|
||||
* {@link NativeQuery} result definition methods.
|
||||
*
|
||||
* @see NativeQuery#addScalar
|
||||
* @see NativeQuery#addInstantiation
|
||||
* @see NativeQuery#addAttributeResult
|
||||
* @see NativeQuery#addEntity
|
||||
* @see NativeQuery#addRoot
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DynamicResultBuilder extends ResultBuilder, NativeQuery.ReturnableResultNode {
|
||||
}
|
@ -4,37 +4,33 @@
|
||||
* 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;
|
||||
package org.hibernate.query.results.dynamic;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* DynamicResultBuilder based on a named mapped attribute
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class AttributeResultBuilder implements ResultBuilder {
|
||||
public class DynamicResultBuilderAttribute implements DynamicResultBuilder {
|
||||
private final BasicValuedSingularAttributeMapping attributeMapping;
|
||||
private final String columnAlias;
|
||||
private final String entityName;
|
||||
private final String attributePath;
|
||||
|
||||
public AttributeResultBuilder(
|
||||
public DynamicResultBuilderAttribute(
|
||||
SingularAttributeMapping attributeMapping,
|
||||
String columnAlias,
|
||||
String entityName,
|
||||
@ -59,14 +55,17 @@ public AttributeResultBuilder(
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildReturn(
|
||||
public DomainResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
final int resultSetPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
|
||||
final int valuesArrayPosition = resultSetPosition - 1;
|
||||
|
||||
// todo (6.0) : TableGroups + `attributeMapping#buldResult`
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, attributeMapping );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
|
@ -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.results.dynamic;
|
||||
|
||||
import org.hibernate.query.results.ResultBuilderBasicValued;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DynamicResultBuilderBasic extends DynamicResultBuilder, ResultBuilderBasicValued {
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.resource.beans.spi.ProvidedInstanceManagedBeanImpl;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* A ResultBuilder for explicitly converted scalar results
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DynamicResultBuilderBasicConverted<O,R> implements DynamicResultBuilderBasic {
|
||||
private final String columnAlias;
|
||||
|
||||
private final JavaTypeDescriptor<O> domainJtd;
|
||||
private final JavaTypeDescriptor<R> jdbcJtd;
|
||||
|
||||
private final BasicValueConverter<O,R> basicValueConverter;
|
||||
|
||||
public DynamicResultBuilderBasicConverted(
|
||||
String columnAlias,
|
||||
Class<O> domainJavaType,
|
||||
Class<R> jdbcJavaType,
|
||||
AttributeConverter<O, R> converter,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
|
||||
this.columnAlias = columnAlias;
|
||||
this.domainJtd = jtdRegistry.getDescriptor( domainJavaType );
|
||||
this.jdbcJtd = jtdRegistry.getDescriptor( jdbcJavaType );
|
||||
|
||||
|
||||
final JavaTypeDescriptor<? extends AttributeConverter> converterJtd = jtdRegistry.getDescriptor( converter.getClass() );
|
||||
final ManagedBean<? extends AttributeConverter<O,R>> bean = new ProvidedInstanceManagedBeanImpl<>( converter );
|
||||
|
||||
this.basicValueConverter = new JpaAttributeConverterImpl(
|
||||
bean,
|
||||
converterJtd,
|
||||
domainJtd,
|
||||
jdbcJtd
|
||||
);
|
||||
}
|
||||
|
||||
public DynamicResultBuilderBasicConverted(
|
||||
String columnAlias,
|
||||
Class<O> domainJavaType,
|
||||
Class<R> jdbcJavaType,
|
||||
Class<? extends AttributeConverter<O,R>> converterJavaType,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final ManagedBeanRegistry beans = sessionFactory.getServiceRegistry().getService( ManagedBeanRegistry.class );
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
|
||||
this.columnAlias = columnAlias;
|
||||
this.domainJtd = jtdRegistry.getDescriptor( domainJavaType );
|
||||
this.jdbcJtd = jtdRegistry.getDescriptor( jdbcJavaType );
|
||||
|
||||
|
||||
final JavaTypeDescriptor<? extends AttributeConverter<O,R>> converterJtd = jtdRegistry.getDescriptor( converterJavaType );
|
||||
final ManagedBean<? extends AttributeConverter<O,R>> bean = beans.getBean( converterJavaType );
|
||||
|
||||
this.basicValueConverter = new JpaAttributeConverterImpl(
|
||||
bean,
|
||||
converterJtd,
|
||||
domainJtd,
|
||||
jdbcJtd
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
final int currentJdbcPosition = resultPosition + 1;
|
||||
|
||||
final int jdbcPosition;
|
||||
if ( columnAlias != null ) {
|
||||
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
|
||||
}
|
||||
else {
|
||||
jdbcPosition = currentJdbcPosition;
|
||||
}
|
||||
|
||||
final TypeConfiguration typeConfiguration = domainResultCreationState.getSqlAstCreationState()
|
||||
.getCreationContext()
|
||||
.getSessionFactory()
|
||||
.getTypeConfiguration();
|
||||
|
||||
final BasicType<?> basicType = typeConfiguration.getBasicTypeRegistry().resolve(
|
||||
basicValueConverter.getRelationalJavaDescriptor(),
|
||||
jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition )
|
||||
);
|
||||
|
||||
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
|
||||
//noinspection unchecked
|
||||
return new BasicResult( valuesArrayPosition, columnAlias, domainJtd, basicValueConverter );
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Standard DynamicResultBuilder for basic values.
|
||||
*
|
||||
* @see org.hibernate.query.NativeQuery#addScalar
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBasic {
|
||||
private final String columnName;
|
||||
private final String resultAlias;
|
||||
|
||||
private final BasicType<?> explicitType;
|
||||
private final JavaTypeDescriptor<?> explicitJavaTypeDescriptor;
|
||||
|
||||
public DynamicResultBuilderBasicStandard(String columnName, String resultAlias) {
|
||||
assert columnName != null;
|
||||
this.columnName = columnName;
|
||||
this.resultAlias = resultAlias != null ? resultAlias : columnName;
|
||||
|
||||
this.explicitType = null;
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
public DynamicResultBuilderBasicStandard(String columnName, String resultAlias, JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
|
||||
assert columnName != null;
|
||||
this.columnName = columnName;
|
||||
this.resultAlias = resultAlias != null ? resultAlias : columnName;
|
||||
|
||||
assert explicitJavaTypeDescriptor != null;
|
||||
this.explicitJavaTypeDescriptor = explicitJavaTypeDescriptor;
|
||||
|
||||
this.explicitType = null;
|
||||
}
|
||||
|
||||
public DynamicResultBuilderBasicStandard(String columnName, String resultAlias, BasicType<?> explicitType) {
|
||||
assert columnName != null;
|
||||
this.columnName = columnName;
|
||||
this.resultAlias = resultAlias != null ? resultAlias : columnName;
|
||||
|
||||
assert explicitType != null;
|
||||
this.explicitType = explicitType;
|
||||
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
public String getColumnName() {
|
||||
return columnName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
final SessionFactoryImplementor sessionFactory = domainResultCreationState.getSqlAstCreationState()
|
||||
.getCreationContext()
|
||||
.getSessionFactory();
|
||||
|
||||
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnName );
|
||||
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
|
||||
|
||||
final BasicType<?> basicType;
|
||||
|
||||
if ( explicitType != null ) {
|
||||
basicType = explicitType;
|
||||
}
|
||||
else if ( explicitJavaTypeDescriptor != null ) {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
|
||||
basicType = typeConfiguration.getBasicTypeRegistry().resolve( explicitJavaTypeDescriptor, sqlTypeDescriptor );
|
||||
}
|
||||
else {
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
|
||||
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||
final JavaTypeDescriptor<?> javaTypeDescriptor = sqlTypeDescriptor.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
|
||||
basicType = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
|
||||
}
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
|
||||
return new BasicResult<>( valuesArrayPosition, resultAlias, explicitJavaTypeDescriptor );
|
||||
}
|
||||
|
||||
}
|
@ -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.results.dynamic;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.query.results.ResultBuilderEntityValued;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DynamicResultBuilderEntity extends DynamicResultBuilder, ResultBuilderEntityValued {
|
||||
@Override
|
||||
EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState);
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.FromClauseAccessImpl;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.TableGroupImpl;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* An entity-valued DynamicResultBuilder for cases when the user has not supplied
|
||||
* specific column -> attribute mappings. Hibernate uses the column names mapped
|
||||
* by the entity mapping itself to read the entity values.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilderEntity {
|
||||
private final NavigablePath navigablePath;
|
||||
private final EntityMappingType entityMapping;
|
||||
|
||||
private final String tableAlias;
|
||||
private final LockMode explicitLockMode;
|
||||
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
|
||||
public DynamicResultBuilderEntityCalculated(
|
||||
EntityMappingType entityMapping,
|
||||
String tableAlias,
|
||||
LockMode explicitLockMode,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
this.entityMapping = entityMapping;
|
||||
this.navigablePath = new NavigablePath( entityMapping.getEntityName() );
|
||||
this.tableAlias = tableAlias;
|
||||
this.explicitLockMode = explicitLockMode;
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
final FromClauseAccessImpl fromClauseAccess = ResultsHelper.extractFromClauseAccess( domainResultCreationState );
|
||||
|
||||
TableGroupImpl.TableReferenceImpl tableReference = new TableGroupImpl.TableReferenceImpl(
|
||||
entityMapping.getEntityName(),
|
||||
tableAlias,
|
||||
false,
|
||||
sessionFactory
|
||||
);
|
||||
|
||||
final TableGroupImpl tableGroup = new TableGroupImpl(
|
||||
navigablePath,
|
||||
tableAlias,
|
||||
tableReference,
|
||||
entityMapping,
|
||||
explicitLockMode
|
||||
);
|
||||
|
||||
fromClauseAccess.registerTableGroup( navigablePath, tableGroup );
|
||||
|
||||
return (EntityResult) entityMapping.createDomainResult(
|
||||
navigablePath,
|
||||
tableGroup,
|
||||
tableAlias,
|
||||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DynamicResultBuilderEntityStandard
|
||||
extends AbstractFetchBuilderContainer<DynamicResultBuilderEntityStandard>
|
||||
implements DynamicResultBuilderEntity, NativeQuery.RootReturn {
|
||||
private final NavigablePath navigablePath;
|
||||
|
||||
private final EntityMappingType entityMapping;
|
||||
private final String tableAlias;
|
||||
|
||||
private LockMode lockMode;
|
||||
|
||||
private String discriminatorColumnName;
|
||||
|
||||
public DynamicResultBuilderEntityStandard(EntityMappingType entityMapping, String tableAlias) {
|
||||
this( entityMapping, tableAlias, null );
|
||||
}
|
||||
|
||||
public DynamicResultBuilderEntityStandard(
|
||||
EntityMappingType entityMapping,
|
||||
String tableAlias,
|
||||
String discriminatorColumnName) {
|
||||
this.navigablePath = new NavigablePath( entityMapping.getEntityName() );
|
||||
|
||||
this.entityMapping = entityMapping;
|
||||
this.tableAlias = tableAlias;
|
||||
|
||||
this.discriminatorColumnName = discriminatorColumnName;
|
||||
}
|
||||
|
||||
public EntityMappingType getEntityMapping() {
|
||||
return entityMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPropertyBase() {
|
||||
return entityMapping.getEntityName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
// final FromClauseAccessImpl fromClauseAccess = ResultsHelper.extractFromClauseAccess( domainResultCreationState );
|
||||
// final TableGroup tableGroup = fromClauseAccess.resolveTableGroup(
|
||||
// navigablePath,
|
||||
// np -> {
|
||||
// final TableGroupImpl.TableReferenceImpl tableReference = new TableGroupImpl.TableReferenceImpl(
|
||||
// entityMapping.getEntityName(),
|
||||
// tableAlias,
|
||||
// false,
|
||||
// domainResultCreationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
|
||||
// );
|
||||
// return new TableGroupImpl( navigablePath, tableAlias, tableReference, entityMapping, lockMode );
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// return new EntityResultImpl(
|
||||
// entityMapping,
|
||||
// tableAlias,
|
||||
// lockMode,
|
||||
// jdbcResultsMetadata,
|
||||
// sqlSelectionConsumer,
|
||||
// () -> {
|
||||
// if ( discriminatorColumnName == null ) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// final int jdbcPosition;
|
||||
// try {
|
||||
// jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( discriminatorColumnName );
|
||||
// }
|
||||
// catch (Exception e) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// final int valuesArrayPosition = jdbcPosition - 1;
|
||||
//
|
||||
// final SqlSelection discriminatorSqlSelection = new SqlSelectionImpl(
|
||||
// valuesArrayPosition,
|
||||
// entityMapping.getDiscriminatorMapping()
|
||||
// );
|
||||
//
|
||||
// sqlSelectionConsumer.accept( discriminatorSqlSelection );
|
||||
//
|
||||
// return discriminatorSqlSelection;
|
||||
// },
|
||||
// // fetchableName -> fetchBuilders.get( fetchableName ),
|
||||
// fetchableName -> null,
|
||||
// legacyFetchResolver,
|
||||
// domainResultCreationState
|
||||
// );
|
||||
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicResultBuilderEntityStandard setLockMode(LockMode lockMode) {
|
||||
this.lockMode = lockMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicResultBuilderEntityStandard setDiscriminatorAlias(String columnName) {
|
||||
this.discriminatorColumnName = columnName;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.query.DynamicInstantiationNature;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.results.Builders;
|
||||
import org.hibernate.query.results.ResultBuilderInstantiationValued;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.instantiation.internal.ArgumentDomainResult;
|
||||
import org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiationResultImpl;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DynamicResultBuilderInstantiation<J>
|
||||
implements DynamicResultBuilder, ResultBuilderInstantiationValued, NativeQuery.InstantiationResultNode<J> {
|
||||
|
||||
private static class InstantiationArgument {
|
||||
private final DynamicResultBuilder argumentBuilder;
|
||||
private final String resultAlias;
|
||||
|
||||
public InstantiationArgument(DynamicResultBuilder argumentBuilder, String resultAlias) {
|
||||
this.argumentBuilder = argumentBuilder;
|
||||
this.resultAlias = resultAlias;
|
||||
}
|
||||
}
|
||||
|
||||
private final JavaTypeDescriptor<J> javaTypeDescriptor;
|
||||
private final List<InstantiationArgument> argumentResultBuilders = new ArrayList<>();
|
||||
|
||||
public DynamicResultBuilderInstantiation(JavaTypeDescriptor<J> javaTypeDescriptor) {
|
||||
this.javaTypeDescriptor = javaTypeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQuery.InstantiationResultNode<J> addBasicArgument(String columnAlias, String argumentAlias) {
|
||||
argumentResultBuilders.add(
|
||||
new InstantiationArgument( Builders.scalar( columnAlias ), argumentAlias )
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
int resultPosition,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
if ( argumentResultBuilders.isEmpty() ) {
|
||||
throw new IllegalStateException( "DynamicResultBuilderInstantiation defined no arguments" );
|
||||
}
|
||||
|
||||
final List<ArgumentDomainResult<?>> argumentDomainResults = new ArrayList<>( argumentResultBuilders.size() );
|
||||
|
||||
for ( int i = 0; i < argumentResultBuilders.size(); i++ ) {
|
||||
final InstantiationArgument argument = argumentResultBuilders.get( i );
|
||||
|
||||
final ArgumentDomainResult<Object> argumentDomainResult = new ArgumentDomainResult<>(
|
||||
argument.argumentBuilder.buildResult(
|
||||
jdbcResultsMetadata,
|
||||
i,
|
||||
legacyFetchResolver,
|
||||
sqlSelectionConsumer,
|
||||
domainResultCreationState
|
||||
)
|
||||
);
|
||||
|
||||
argumentDomainResults.add( argumentDomainResult );
|
||||
}
|
||||
|
||||
return new DynamicInstantiationResultImpl(
|
||||
null,
|
||||
DynamicInstantiationNature.CLASS,
|
||||
javaTypeDescriptor,
|
||||
argumentDomainResults
|
||||
);
|
||||
}
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for mutable result/fetch builder graphs nodes built dynamically via
|
||||
* Hibernate's {@link org.hibernate.query.NativeQuery} APIs
|
||||
*
|
||||
* @see org.hibernate.query.NativeQuery#addScalar
|
||||
* @see org.hibernate.query.NativeQuery#addEntity
|
||||
* @see org.hibernate.query.NativeQuery#addJoin
|
||||
* @see org.hibernate.query.NativeQuery#addFetch
|
||||
* @see org.hibernate.query.NativeQuery#addRoot
|
||||
*/
|
||||
package org.hibernate.query.results.dynamic;
|
@ -9,7 +9,14 @@
|
||||
* Support for defining result-set mappings used in {@link org.hibernate.query.NativeQuery}
|
||||
* and {@link org.hibernate.procedure.ProcedureCall} / {@link javax.persistence.StoredProcedureQuery}.
|
||||
* These result-set mappings are used to map the values in the JDBC {@link java.sql.ResultSet}
|
||||
* into "domain results" (see {@link org.hibernate.sql.results.graph.DomainResult}).
|
||||
* into the query result graph.
|
||||
*
|
||||
* NOTE : Handling the different sources of results and fetches is split into 2 packages
|
||||
* for performance reasons. The classes in {@link org.hibernate.query.results.complete}
|
||||
* represent result/fetch definitions that are completely known up-front and are faster to
|
||||
* resolve. The definitions in {@link org.hibernate.query.results.dynamic} are built incrementally
|
||||
* via Hibernate's {@link org.hibernate.query.NativeQuery} contract need to resolve themselves
|
||||
* against other dynamic result/fetch definitions and therefore take more resources to resolve
|
||||
*
|
||||
* @see org.hibernate.query.results.ResultSetMapping
|
||||
*
|
||||
|
@ -58,12 +58,14 @@
|
||||
import org.hibernate.query.internal.ParameterMetadataImpl;
|
||||
import org.hibernate.query.internal.QueryOptionsImpl;
|
||||
import org.hibernate.query.internal.QueryParameterBindingsImpl;
|
||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.results.Builders;
|
||||
import org.hibernate.query.results.EntityResultBuilder;
|
||||
import org.hibernate.query.results.LegacyFetchBuilder;
|
||||
import org.hibernate.query.results.ResultBuilder;
|
||||
import org.hibernate.query.results.ResultSetMappingImpl;
|
||||
import org.hibernate.query.results.dynamic.DynamicResultBuilderEntityStandard;
|
||||
import org.hibernate.query.results.dynamic.DynamicResultBuilderInstantiation;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.query.spi.AbstractQuery;
|
||||
import org.hibernate.query.spi.MutableQueryOptions;
|
||||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||
@ -96,7 +98,7 @@
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class NativeQueryImpl<R>
|
||||
extends AbstractQuery<R>
|
||||
implements NativeQueryImplementor<R>, ExecutionContext {
|
||||
implements NativeQueryImplementor<R>, ExecutionContext, ResultSetMappingResolutionContext {
|
||||
private final String sqlString;
|
||||
|
||||
private final ParameterMetadataImplementor parameterMetadata;
|
||||
@ -159,7 +161,7 @@ public NativeQueryImpl(
|
||||
.getQueryEngine()
|
||||
.getNamedQueryRepository()
|
||||
.getResultSetMappingMemento( resultSetMappingName )
|
||||
.resolve( resultSetMapping, (s) -> {}, getSessionFactory() );
|
||||
.resolve( resultSetMapping, (s) -> {}, this );
|
||||
}
|
||||
|
||||
public NativeQueryImpl(
|
||||
@ -169,7 +171,7 @@ public NativeQueryImpl(
|
||||
super( session );
|
||||
|
||||
this.sqlString = sqlString;
|
||||
resultSetMappingMemento.resolve( resultSetMapping, (s) -> {}, getSessionFactory() );
|
||||
resultSetMappingMemento.resolve( resultSetMapping, (s) -> {}, this );
|
||||
|
||||
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session );
|
||||
|
||||
@ -518,9 +520,18 @@ public NativeQueryImplementor<R> addScalar(String columnAlias, Class<?> javaType
|
||||
@Override
|
||||
public <C> NativeQueryImplementor<R> addScalar(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
Class<C> jdbcJavaType,
|
||||
AttributeConverter<?, C> converter) {
|
||||
return registerBuilder( Builders.scalar( columnAlias, relationalJavaType, converter, getSessionFactory() ) );
|
||||
return registerBuilder( Builders.converted( columnAlias, jdbcJavaType, converter, getSessionFactory() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <O, J> NativeQueryImplementor<R> addScalar(
|
||||
String columnAlias,
|
||||
Class<O> domainJavaType,
|
||||
Class<J> jdbcJavaType,
|
||||
AttributeConverter<O, J> converter) {
|
||||
return registerBuilder( Builders.converted( columnAlias, domainJavaType, jdbcJavaType, converter, getSessionFactory() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -528,7 +539,26 @@ public <C> NativeQueryImplementor<R> addScalar(
|
||||
String columnAlias,
|
||||
Class<C> relationalJavaType,
|
||||
Class<? extends AttributeConverter<?, C>> converter) {
|
||||
return registerBuilder( Builders.scalar( columnAlias, relationalJavaType, converter, getSessionFactory() ) );
|
||||
return registerBuilder( Builders.converted( columnAlias, relationalJavaType, converter, getSessionFactory() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <O, J> NativeQueryImplementor<R> addScalar(
|
||||
String columnAlias,
|
||||
Class<O> domainJavaType,
|
||||
Class<J> jdbcJavaType,
|
||||
Class<? extends AttributeConverter<O, J>> converterJavaType) {
|
||||
return registerBuilder( Builders.converted( columnAlias, domainJavaType, jdbcJavaType, converterJavaType, getSessionFactory() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <J> InstantiationResultNode<J> addInstantiation(Class<J> targetJavaType) {
|
||||
final DynamicResultBuilderInstantiation<J> builder = Builders.instantiation(
|
||||
targetJavaType,
|
||||
getSessionFactory()
|
||||
);
|
||||
registerBuilder( builder );
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -557,17 +587,18 @@ public NativeQueryImplementor<R> addAttributeResult(
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResultBuilder addRoot(String tableAlias, String entityName) {
|
||||
final EntityResultBuilder resultBuilder = Builders.entity(
|
||||
public DynamicResultBuilderEntityStandard addRoot(String tableAlias, String entityName) {
|
||||
final DynamicResultBuilderEntityStandard resultBuilder = Builders.entity(
|
||||
tableAlias,
|
||||
entityName
|
||||
entityName,
|
||||
getSessionFactory()
|
||||
);
|
||||
resultSetMapping.addResultBuilder( resultBuilder );
|
||||
return resultBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResultBuilder addRoot(String tableAlias, Class entityType) {
|
||||
public DynamicResultBuilderEntityStandard addRoot(String tableAlias, Class entityType) {
|
||||
return addRoot( tableAlias, entityType.getName() );
|
||||
}
|
||||
|
||||
@ -578,13 +609,13 @@ public NativeQueryImplementor<R> addEntity(String entityName) {
|
||||
|
||||
@Override
|
||||
public NativeQueryImplementor<R> addEntity(String tableAlias, String entityName) {
|
||||
registerBuilder( Builders.entityCalculated( tableAlias, entityName ) );
|
||||
registerBuilder( Builders.entityCalculated( tableAlias, entityName, getSessionFactory() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQueryImplementor<R> addEntity(String tableAlias, String entityName, LockMode lockMode) {
|
||||
registerBuilder( Builders.entityCalculated( tableAlias, entityName, lockMode ) );
|
||||
registerBuilder( Builders.entityCalculated( tableAlias, entityName, lockMode, getSessionFactory() ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -605,7 +636,7 @@ public NativeQueryImplementor<R> addEntity(String tableAlias, Class entityClass,
|
||||
|
||||
@Override
|
||||
public FetchReturn addFetch(String tableAlias, String ownerTableAlias, String joinPropertyName) {
|
||||
final LegacyFetchBuilder fetchBuilder = Builders.fetch( tableAlias, ownerTableAlias, joinPropertyName );
|
||||
final DynamicFetchBuilderLegacy fetchBuilder = Builders.fetch( tableAlias, ownerTableAlias, joinPropertyName );
|
||||
resultSetMapping.addLegacyFetchBuilder( fetchBuilder );
|
||||
return fetchBuilder;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
import org.hibernate.query.ResultListTransformer;
|
||||
import org.hibernate.query.TupleTransformer;
|
||||
import org.hibernate.query.named.NameableQuery;
|
||||
import org.hibernate.query.results.EntityResultBuilder;
|
||||
import org.hibernate.query.results.dynamic.DynamicResultBuilderEntityStandard;
|
||||
import org.hibernate.query.spi.QueryImplementor;
|
||||
|
||||
/**
|
||||
@ -63,9 +63,19 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
|
||||
@Override
|
||||
<C> NativeQueryImplementor<R> addScalar(String columnAlias, Class<C> relationalJavaType, AttributeConverter<?,C> converter);
|
||||
|
||||
@Override
|
||||
<O, J> NativeQueryImplementor<R> addScalar(String columnAlias, Class<O> domainJavaType, Class<J> jdbcJavaType, AttributeConverter<O, J> converter);
|
||||
|
||||
@Override
|
||||
<C> NativeQueryImplementor<R> addScalar(String columnAlias, Class<C> relationalJavaType, Class<? extends AttributeConverter<?,C>> converter);
|
||||
|
||||
@Override
|
||||
<O, J> NativeQueryImplementor<R> addScalar(
|
||||
String columnAlias,
|
||||
Class<O> domainJavaType,
|
||||
Class<J> jdbcJavaType,
|
||||
Class<? extends AttributeConverter<O, J>> converter);
|
||||
|
||||
@Override
|
||||
NativeQueryImplementor<R> addAttributeResult(String columnAlias, Class<?> entityJavaType, String attributePath);
|
||||
|
||||
@ -76,7 +86,7 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
|
||||
NativeQueryImplementor<R> addAttributeResult(String columnAlias, SingularAttribute<?, ?> attribute);
|
||||
|
||||
@Override
|
||||
EntityResultBuilder addRoot(String tableAlias, String entityName);
|
||||
DynamicResultBuilderEntityStandard addRoot(String tableAlias, String entityName);
|
||||
|
||||
@Override
|
||||
NativeQueryImplementor<R> addEntity(String entityName);
|
||||
|
@ -87,9 +87,7 @@ public Expression resolveSqlExpression(
|
||||
expressionMap.put( key, expression );
|
||||
}
|
||||
|
||||
final Expression result = normalize( expression );
|
||||
|
||||
return result;
|
||||
return expression;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
|
@ -8,12 +8,10 @@
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.mapping.AssociationKey;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValues;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityResultImpl extends AbstractEntityResultGraphNode implements EntityResult {
|
||||
|
||||
private final String resultVariable;
|
||||
|
||||
public EntityResultImpl(
|
||||
|
@ -28,5 +28,7 @@ public interface JdbcValuesMappingProducer {
|
||||
* {@link org.hibernate.sql.results.graph.DomainResult} and
|
||||
* {@link org.hibernate.sql.results.graph.Fetch}
|
||||
*/
|
||||
JdbcValuesMapping resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory);
|
||||
JdbcValuesMapping resolve(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
SessionFactoryImplementor sessionFactory);
|
||||
}
|
||||
|
@ -1,36 +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.type.descriptor;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EmptyJdbcValueExtractor implements ValueExtractor {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final EmptyJdbcValueExtractor INSTANCE = new EmptyJdbcValueExtractor();
|
||||
|
||||
@Override
|
||||
public Object extract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object extract(CallableStatement statement, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object extract(CallableStatement statement, String paramName, WrapperOptions options) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
import javax.persistence.ColumnResult;
|
||||
import javax.persistence.ConstructorResult;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityResult;
|
||||
import javax.persistence.FieldResult;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.SqlResultSetMapping;
|
||||
|
||||
@ -37,6 +39,16 @@
|
||||
}
|
||||
)
|
||||
)
|
||||
@SqlResultSetMapping(
|
||||
name = "entity",
|
||||
entities = @EntityResult(
|
||||
entityClass = SimpleEntityWithNamedMappings.class,
|
||||
fields = {
|
||||
@FieldResult( name = "id", column = "id" ),
|
||||
@FieldResult( name = "name", column = "name" )
|
||||
}
|
||||
)
|
||||
)
|
||||
public class SimpleEntityWithNamedMappings {
|
||||
@Id
|
||||
private Integer id;
|
||||
|
@ -6,6 +6,8 @@
|
||||
*/
|
||||
package org.hibernate.orm.test.query.named.resultmapping;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||
import org.hibernate.query.named.NamedQueryRepository;
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.results.ResultSetMapping;
|
||||
@ -33,7 +35,15 @@ public void testMappingResolution(SessionFactoryScope sessionFactoryScope) {
|
||||
final NamedResultSetMappingMemento mappingMemento = namedQueryRepository.getResultSetMappingMemento( "name" );
|
||||
|
||||
final ResultSetMapping mapping = new ResultSetMappingImpl();
|
||||
mappingMemento.resolve( mapping, querySpace -> {}, sessionFactoryScope.getSessionFactory() );
|
||||
|
||||
final ResultSetMappingResolutionContext resolutionContext = new ResultSetMappingResolutionContext() {
|
||||
@Override
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return sessionFactoryScope.getSessionFactory();
|
||||
}
|
||||
};
|
||||
|
||||
mappingMemento.resolve( mapping, querySpace -> {}, resolutionContext );
|
||||
|
||||
assertThat( mapping.getNumberOfResultBuilders(), is( 1 ) );
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -27,6 +28,7 @@
|
||||
@DomainModel( annotatedClasses = SimpleEntityWithNamedMappings.class )
|
||||
@SessionFactory
|
||||
public class UsageTests {
|
||||
// select a.{*}
|
||||
@Test
|
||||
public void testSimpleScalarMapping(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
@ -75,6 +77,34 @@ public void testSimpleInstantiationOfScalars(SessionFactoryScope scope) {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( reason = "Entity result mappings not yet implemented" )
|
||||
public void testSimpleEntityResultMapping(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
// make sure it is in the repository
|
||||
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
|
||||
.getQueryEngine()
|
||||
.getNamedQueryRepository()
|
||||
.getResultSetMappingMemento( "entity" );
|
||||
assertThat( mappingMemento, notNullValue() );
|
||||
|
||||
// apply it to a native-query
|
||||
final String qryString = "select id, name from SimpleEntityWithNamedMappings";
|
||||
final List<SimpleEntityWithNamedMappings> results
|
||||
= session.createNativeQuery( qryString, "entity" ).list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
|
||||
final SimpleEntityWithNamedMappings entity = results.get( 0 );
|
||||
assertThat( entity.getId(), is( 1 ) );
|
||||
assertThat( entity.getName(), is( "test" ) );
|
||||
|
||||
// todo (6.0) : should also try executing the ProcedureCall once that functionality is implemented
|
||||
session.createStoredProcedureCall( "abc", "entity" );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void prepareData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
|
@ -17,6 +17,7 @@
|
||||
import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
||||
|
||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||
@ -71,6 +72,25 @@ public void fullyImplicitTest(SessionFactoryScope scope) {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullyImplicitTest2(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final String sql = "select count(theString) from EntityOfBasics";
|
||||
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||
|
||||
final List<?> results = query.list();
|
||||
assertThat( results.size(), is( 1 ) );
|
||||
|
||||
final Object result = results.get( 0 );
|
||||
assertThat( result, instanceOf( Long.class ) );
|
||||
|
||||
assertThat( result, is( 1L ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void explicitOrderTest(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
@ -174,6 +194,7 @@ public void explicitConversionTest(SessionFactoryScope scope) {
|
||||
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||
query.addScalar(
|
||||
"converted_gender",
|
||||
EntityOfBasics.Gender.class,
|
||||
Character.class,
|
||||
new EntityOfBasics.GenderConverter()
|
||||
);
|
||||
@ -194,6 +215,7 @@ public void explicitConversionTest(SessionFactoryScope scope) {
|
||||
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||
query.addScalar(
|
||||
"converted_gender",
|
||||
EntityOfBasics.Gender.class,
|
||||
Character.class,
|
||||
EntityOfBasics.GenderConverter.class
|
||||
);
|
||||
@ -296,4 +318,35 @@ public void cleanUpData(SessionFactoryScope scope) {
|
||||
session -> session.createQuery( "delete EntityOfBasics" ).executeUpdate()
|
||||
);
|
||||
}
|
||||
|
||||
public static class DTO {
|
||||
private Integer key;
|
||||
private String text;
|
||||
|
||||
public DTO(Integer key, String text) {
|
||||
this.key = key;
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Bean {
|
||||
private Integer key;
|
||||
private String text;
|
||||
|
||||
public Integer getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(Integer key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user