ResultSet mapping
- Support for implicit and mixed attribute mappings for `@EntityResult`
This commit is contained in:
parent
b744d7891c
commit
b7eed1842c
|
@ -34,6 +34,7 @@ import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping
|
||||||
import org.hibernate.query.EntityIdentifierNavigablePath;
|
import org.hibernate.query.EntityIdentifierNavigablePath;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.internal.FetchMementoBasicStandard;
|
import org.hibernate.query.internal.FetchMementoBasicStandard;
|
||||||
|
import org.hibernate.query.internal.ImplicitModelPartResultMemento;
|
||||||
import org.hibernate.query.internal.ModelPartResultMementoBasicImpl;
|
import org.hibernate.query.internal.ModelPartResultMementoBasicImpl;
|
||||||
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl;
|
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl;
|
||||||
import org.hibernate.query.internal.ResultMementoBasicStandard;
|
import org.hibernate.query.internal.ResultMementoBasicStandard;
|
||||||
|
@ -46,6 +47,7 @@ import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
import org.hibernate.query.named.ResultMemento;
|
import org.hibernate.query.named.ResultMemento;
|
||||||
import org.hibernate.query.named.ResultMementoBasic;
|
import org.hibernate.query.named.ResultMementoBasic;
|
||||||
import org.hibernate.query.named.ResultMementoInstantiation.ArgumentMemento;
|
import org.hibernate.query.named.ResultMementoInstantiation.ArgumentMemento;
|
||||||
|
import org.hibernate.query.results.ResultsHelper;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -271,9 +273,6 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
||||||
final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels();
|
final RuntimeMetamodels runtimeMetamodels = resolutionContext.getSessionFactory().getRuntimeMetamodels();
|
||||||
final EntityMappingType entityDescriptor = runtimeMetamodels.getEntityMappingType( entityName );
|
final EntityMappingType entityDescriptor = runtimeMetamodels.getEntityMappingType( entityName );
|
||||||
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
||||||
final String identifierAttributeName = identifierMapping instanceof SingleAttributeIdentifierMapping
|
|
||||||
? ( (SingleAttributeIdentifierMapping) identifierMapping ).getAttributeName()
|
|
||||||
: EntityIdentifierMapping.ROLE_LOCAL_NAME;
|
|
||||||
|
|
||||||
final MutableObject<ResultMemento> identifierMementoReference = new MutableObject<>();
|
final MutableObject<ResultMemento> identifierMementoReference = new MutableObject<>();
|
||||||
|
|
||||||
|
@ -284,30 +283,65 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
||||||
);
|
);
|
||||||
|
|
||||||
final Map<String, FetchMemento> fetchMementos = new HashMap<>();
|
final Map<String, FetchMemento> fetchMementos = new HashMap<>();
|
||||||
fetchMappings.forEach(
|
|
||||||
(attrName, attrMapping) -> {
|
|
||||||
if ( EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( attrName )
|
entityDescriptor.visitAttributeMappings(
|
||||||
|| identifierAttributeName.equals( attrName ) ) {
|
attributeMapping -> {
|
||||||
|
final String fetchableName = attributeMapping.getFetchableName();
|
||||||
|
final String attrNameName = attributeMapping.getAttributeName();
|
||||||
|
|
||||||
|
final boolean isIdentifier = ResultsHelper.isIdentifier(
|
||||||
|
identifierMapping,
|
||||||
|
fetchableName,
|
||||||
|
attrNameName
|
||||||
|
);
|
||||||
|
|
||||||
|
final AttributeFetchDescriptor fetchDescriptor = fetchMappings.get( fetchableName );
|
||||||
|
|
||||||
|
if ( isIdentifier ) {
|
||||||
|
final ResultMemento idResultMemento;
|
||||||
|
|
||||||
final EntityIdentifierNavigablePath idPath = new EntityIdentifierNavigablePath( navigablePath );
|
final EntityIdentifierNavigablePath idPath = new EntityIdentifierNavigablePath( navigablePath );
|
||||||
identifierMementoReference.set( attrMapping.asResultMemento( idPath, resolutionContext ) );
|
if ( fetchDescriptor == null ) {
|
||||||
|
final AttributeFetchDescriptor idRoleFetchDescriptor = fetchMappings.get( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
||||||
|
if ( idRoleFetchDescriptor == null ) {
|
||||||
|
idResultMemento = ResultsHelper.implicitIdentifierResult( identifierMapping, idPath, resolutionContext );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
idResultMemento = idRoleFetchDescriptor.asResultMemento( idPath, resolutionContext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
idResultMemento = fetchDescriptor.asResultMemento( idPath, resolutionContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
identifierMementoReference.set( idResultMemento );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fetchMementos.put( attrName, attrMapping.resolve( resolutionContext ) );
|
final NavigablePath fetchPath = navigablePath.append( fetchableName );
|
||||||
|
|
||||||
|
final FetchMemento fetchMemento;
|
||||||
|
if ( fetchDescriptor == null ) {
|
||||||
|
fetchMemento = ResultsHelper.implicitFetch( attributeMapping, fetchPath, resolutionContext );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fetchMemento = fetchDescriptor.resolve( resolutionContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchMementos.put( fetchableName, fetchMemento );
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( identifierMementoReference.isNotSet() ) {
|
if ( identifierMementoReference.isNotSet() ) {
|
||||||
throw new IllegalStateException(
|
final EntityIdentifierNavigablePath idPath = new EntityIdentifierNavigablePath( navigablePath );
|
||||||
String.format(
|
identifierMementoReference.set( new ImplicitModelPartResultMemento( idPath, identifierMapping ) );
|
||||||
Locale.ROOT,
|
|
||||||
"Entity identifier mapping not specified for @EntityResult(%s) for ResultSet mapping `%s`",
|
|
||||||
entityDescriptor.getEntityName(),
|
|
||||||
resultSetMappingName
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert entityDescriptor.getNumberOfAttributeMappings() == fetchMementos.size();
|
||||||
|
assert identifierMementoReference.isSet();
|
||||||
|
|
||||||
return new ResultMementoEntityStandard(
|
return new ResultMementoEntityStandard(
|
||||||
entityDescriptor,
|
entityDescriptor,
|
||||||
LockMode.READ,
|
LockMode.READ,
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
package org.hibernate.metamodel.mapping;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
import org.hibernate.property.access.spi.PropertyAccess;
|
import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
|
import org.hibernate.sql.results.graph.Fetchable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes an attribute at the mapping model level.
|
* Describes an attribute at the mapping model level.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface AttributeMapping extends ModelPart, ValueMapping {
|
public interface AttributeMapping extends ModelPart, ValueMapping, Fetchable {
|
||||||
String getAttributeName();
|
String getAttributeName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.AttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.named.FetchMemento;
|
||||||
|
import org.hibernate.query.results.FetchBuilder;
|
||||||
|
import org.hibernate.query.results.ImplicitAttributeFetchBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class ImplicitAttributeFetchMemento implements FetchMemento {
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final AttributeMapping attributeMapping;
|
||||||
|
|
||||||
|
public ImplicitAttributeFetchMemento(NavigablePath navigablePath, AttributeMapping attributeMapping) {
|
||||||
|
this.navigablePath = navigablePath;
|
||||||
|
this.attributeMapping = attributeMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingType getMappingType() {
|
||||||
|
return attributeMapping.getPartMappingType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchBuilder resolve(
|
||||||
|
Parent parent,
|
||||||
|
Consumer<String> querySpaceConsumer,
|
||||||
|
ResultSetMappingResolutionContext context) {
|
||||||
|
return new ImplicitAttributeFetchBuilder( navigablePath, attributeMapping );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeMapping getReferencedModelPart() {
|
||||||
|
return attributeMapping;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.query.internal;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.named.ModelPartResultMemento;
|
||||||
|
import org.hibernate.query.named.ModelPartResultMementoBasic;
|
||||||
|
import org.hibernate.query.results.ImplicitModelPartResultBuilder;
|
||||||
|
import org.hibernate.query.results.ResultBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class ImplicitModelPartResultMemento implements ModelPartResultMemento {
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final ModelPart referencedModelPart;
|
||||||
|
|
||||||
|
public ImplicitModelPartResultMemento(NavigablePath navigablePath, ModelPart referencedModelPart) {
|
||||||
|
this.navigablePath = navigablePath;
|
||||||
|
this.referencedModelPart = referencedModelPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getReferencedModelPart() {
|
||||||
|
return referencedModelPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultBuilder resolve(
|
||||||
|
Consumer<String> querySpaceConsumer,
|
||||||
|
ResultSetMappingResolutionContext context) {
|
||||||
|
return new ImplicitModelPartResultBuilder(
|
||||||
|
navigablePath,
|
||||||
|
null,
|
||||||
|
referencedModelPart
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ import org.hibernate.sql.results.ResultsLogger;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.sql.results.graph.Fetch;
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
import org.hibernate.sql.results.graph.FetchParent;
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
@ -47,8 +48,9 @@ public class DomainResultCreationStateImpl
|
||||||
private final String stateIdentifier;
|
private final String stateIdentifier;
|
||||||
private final FromClauseAccessImpl fromClauseAccess;
|
private final FromClauseAccessImpl fromClauseAccess;
|
||||||
|
|
||||||
|
private final JdbcValuesMetadata jdbcResultsMetadata;
|
||||||
private final Consumer<SqlSelection> sqlSelectionConsumer;
|
private final Consumer<SqlSelection> sqlSelectionConsumer;
|
||||||
private final Map<String,SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
|
private final Map<String, SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
|
||||||
private boolean allowPositionalSelections = true;
|
private boolean allowPositionalSelections = true;
|
||||||
|
|
||||||
private final SqlAliasBaseManager sqlAliasBaseManager;
|
private final SqlAliasBaseManager sqlAliasBaseManager;
|
||||||
|
@ -59,10 +61,12 @@ public class DomainResultCreationStateImpl
|
||||||
|
|
||||||
public DomainResultCreationStateImpl(
|
public DomainResultCreationStateImpl(
|
||||||
String stateIdentifier,
|
String stateIdentifier,
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders,
|
Map<String, Map<String, DynamicFetchBuilderLegacy>> legacyFetchBuilders,
|
||||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
this.stateIdentifier = stateIdentifier;
|
this.stateIdentifier = stateIdentifier;
|
||||||
|
this.jdbcResultsMetadata = jdbcResultsMetadata;
|
||||||
this.sqlSelectionConsumer = sqlSelectionConsumer;
|
this.sqlSelectionConsumer = sqlSelectionConsumer;
|
||||||
this.fromClauseAccess = new FromClauseAccessImpl();
|
this.fromClauseAccess = new FromClauseAccessImpl();
|
||||||
this.sqlAliasBaseManager = new SqlAliasBaseManager();
|
this.sqlAliasBaseManager = new SqlAliasBaseManager();
|
||||||
|
@ -93,6 +97,11 @@ public class DomainResultCreationStateImpl
|
||||||
this.allowPositionalSelections = false;
|
this.allowPositionalSelections = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JdbcValuesMetadata getJdbcResultsMetadata() {
|
||||||
|
return jdbcResultsMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// DomainResultCreationState
|
// DomainResultCreationState
|
||||||
|
|
||||||
|
@ -200,14 +209,19 @@ public class DomainResultCreationStateImpl
|
||||||
}
|
}
|
||||||
else if ( created instanceof ColumnReference ) {
|
else if ( created instanceof ColumnReference ) {
|
||||||
final ColumnReference columnReference = (ColumnReference) created;
|
final ColumnReference columnReference = (ColumnReference) created;
|
||||||
|
final String columnExpression = columnReference.getColumnExpression();
|
||||||
|
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnExpression );
|
||||||
|
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
|
||||||
|
|
||||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl(
|
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl(
|
||||||
sqlSelectionMap.size() + 1,
|
valuesArrayPosition,
|
||||||
columnReference.getJdbcMapping()
|
columnReference.getJdbcMapping()
|
||||||
);
|
);
|
||||||
|
|
||||||
sqlSelectionMap.put( key, sqlSelection );
|
sqlSelectionMap.put( key, sqlSelection );
|
||||||
sqlSelectionConsumer.accept( sqlSelection );
|
sqlSelectionConsumer.accept( sqlSelection );
|
||||||
|
|
||||||
|
return sqlSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
return created;
|
return created;
|
||||||
|
@ -218,6 +232,9 @@ public class DomainResultCreationStateImpl
|
||||||
Expression expression,
|
Expression expression,
|
||||||
JavaTypeDescriptor javaTypeDescriptor,
|
JavaTypeDescriptor javaTypeDescriptor,
|
||||||
TypeConfiguration typeConfiguration) {
|
TypeConfiguration typeConfiguration) {
|
||||||
|
if ( expression == null ) {
|
||||||
|
throw new IllegalArgumentException( "Expression cannot be null" );
|
||||||
|
}
|
||||||
assert expression instanceof SqlSelectionImpl;
|
assert expression instanceof SqlSelectionImpl;
|
||||||
return (SqlSelection) expression;
|
return (SqlSelection) expression;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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 org.hibernate.LockMode;
|
||||||
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FetchBuilder used when an explicit mapping was not given
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class ImplicitAttributeFetchBuilder implements FetchBuilder {
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final AttributeMapping attributeMapping;
|
||||||
|
|
||||||
|
public ImplicitAttributeFetchBuilder(NavigablePath navigablePath, AttributeMapping attributeMapping) {
|
||||||
|
this.navigablePath = navigablePath;
|
||||||
|
this.attributeMapping = attributeMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetch buildFetch(
|
||||||
|
FetchParent parent,
|
||||||
|
NavigablePath fetchPath,
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||||
|
DomainResultCreationState domainResultCreationState) {
|
||||||
|
assert fetchPath.equals( navigablePath );
|
||||||
|
|
||||||
|
return attributeMapping.generateFetch(
|
||||||
|
parent,
|
||||||
|
fetchPath,
|
||||||
|
FetchTiming.IMMEDIATE,
|
||||||
|
true,
|
||||||
|
LockMode.READ,
|
||||||
|
null,
|
||||||
|
domainResultCreationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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 org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class ImplicitModelPartResultBuilder implements ResultBuilder {
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final String alias;
|
||||||
|
private final ModelPart referencedModelPart;
|
||||||
|
|
||||||
|
public ImplicitModelPartResultBuilder(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
String alias,
|
||||||
|
ModelPart referencedModelPart) {
|
||||||
|
this.navigablePath = navigablePath;
|
||||||
|
this.alias = alias;
|
||||||
|
this.referencedModelPart = referencedModelPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResult<?> buildResult(
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
int resultPosition,
|
||||||
|
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||||
|
DomainResultCreationState domainResultCreationState) {
|
||||||
|
final DomainResultCreationStateImpl impl = ResultsHelper.impl( domainResultCreationState );
|
||||||
|
|
||||||
|
ResultsHelper.impl( domainResultCreationState ).disallowPositionalSelections();
|
||||||
|
;
|
||||||
|
return referencedModelPart.createDomainResult(
|
||||||
|
navigablePath,
|
||||||
|
impl.getFromClauseAccess().resolveTableGroup(
|
||||||
|
navigablePath,
|
||||||
|
np -> impl.getFromClauseAccess().getTableGroup( navigablePath.getParent() )
|
||||||
|
),
|
||||||
|
alias,
|
||||||
|
domainResultCreationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -115,6 +115,7 @@ public class ResultSetMappingImpl implements ResultSetMapping {
|
||||||
|
|
||||||
final DomainResultCreationStateImpl creationState = new DomainResultCreationStateImpl(
|
final DomainResultCreationStateImpl creationState = new DomainResultCreationStateImpl(
|
||||||
mappingIdentifier,
|
mappingIdentifier,
|
||||||
|
jdbcResultsMetadata,
|
||||||
legacyFetchBuilders,
|
legacyFetchBuilders,
|
||||||
sqlSelections::add,
|
sqlSelections::add,
|
||||||
sessionFactory
|
sessionFactory
|
||||||
|
|
|
@ -6,7 +6,21 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.results;
|
package org.hibernate.query.results;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
|
||||||
|
import org.hibernate.query.EntityIdentifierNavigablePath;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.internal.ImplicitAttributeFetchMemento;
|
||||||
|
import org.hibernate.query.internal.ImplicitModelPartResultMemento;
|
||||||
|
import org.hibernate.query.internal.ModelPartResultMementoBasicImpl;
|
||||||
|
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||||
|
import org.hibernate.query.named.FetchMemento;
|
||||||
|
import org.hibernate.query.named.ResultMemento;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -36,4 +50,37 @@ public class ResultsHelper {
|
||||||
|
|
||||||
private ResultsHelper() {
|
private ResultsHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isIdentifier(EntityIdentifierMapping identifierDescriptor, String... names) {
|
||||||
|
final String identifierAttributeName = identifierDescriptor instanceof SingleAttributeIdentifierMapping
|
||||||
|
? ( (SingleAttributeIdentifierMapping) identifierDescriptor ).getAttributeName()
|
||||||
|
: EntityIdentifierMapping.ROLE_LOCAL_NAME;
|
||||||
|
|
||||||
|
for ( int i = 0; i < names.length; i++ ) {
|
||||||
|
final String name = names[ i ];
|
||||||
|
if ( EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( name ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( identifierAttributeName.equals( name ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResultMemento implicitIdentifierResult(
|
||||||
|
EntityIdentifierMapping identifierMapping,
|
||||||
|
EntityIdentifierNavigablePath idPath,
|
||||||
|
ResultSetMappingResolutionContext resolutionContext) {
|
||||||
|
return new ImplicitModelPartResultMemento( idPath, identifierMapping );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FetchMemento implicitFetch(
|
||||||
|
AttributeMapping attributeMapping,
|
||||||
|
NavigablePath attributePath,
|
||||||
|
ResultSetMappingResolutionContext resolutionContext) {
|
||||||
|
return new ImplicitAttributeFetchMemento( attributePath, attributeMapping );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class SqlAstCreationStateImpl implements SqlAstCreationState, SqlAstProce
|
||||||
private final SqlAliasBaseManager sqlAliasBaseManager;
|
private final SqlAliasBaseManager sqlAliasBaseManager;
|
||||||
|
|
||||||
private final Consumer<SqlSelection> sqlSelectionConsumer;
|
private final Consumer<SqlSelection> sqlSelectionConsumer;
|
||||||
private final Map<String,SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
|
private final Map<String, SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
|
||||||
|
|
||||||
private final SessionFactoryImplementor sessionFactory;
|
private final SessionFactoryImplementor sessionFactory;
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ import org.hibernate.type.spi.TypeConfiguration;
|
||||||
public class SqlAstProcessingStateImpl implements SqlAstProcessingState, SqlExpressionResolver {
|
public class SqlAstProcessingStateImpl implements SqlAstProcessingState, SqlExpressionResolver {
|
||||||
private final FromClauseAccessImpl fromClauseAccess;
|
private final FromClauseAccessImpl fromClauseAccess;
|
||||||
|
|
||||||
private final Map<String,SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
|
private final Map<String, SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
|
||||||
private final Consumer<SqlSelection> sqlSelectionConsumer;
|
private final Consumer<SqlSelection> sqlSelectionConsumer;
|
||||||
|
|
||||||
private final SqlAstCreationState sqlAstCreationState;
|
private final SqlAstCreationState sqlAstCreationState;
|
||||||
|
|
|
@ -11,7 +11,6 @@ import java.util.function.BiFunction;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping;
|
import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping;
|
||||||
import org.hibernate.query.results.ResultsHelper;
|
|
||||||
import org.hibernate.query.results.SqlSelectionImpl;
|
import org.hibernate.query.results.SqlSelectionImpl;
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.query.resultmapping;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@DomainModel( annotatedClasses = SimpleEntityWithNamedMappings.class )
|
||||||
|
@SessionFactory
|
||||||
|
public class BaseUsageTest {
|
||||||
|
@BeforeEach
|
||||||
|
public void prepareData(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.save( new SimpleEntityWithNamedMappings( 1, "test" ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void cleanUpData(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "delete SimpleEntityWithNamedMappings" ).executeUpdate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.query.resultmapping;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class BasicResultTests extends BaseUsageTest {
|
||||||
|
@Test
|
||||||
|
public void testSimpleScalarMapping(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
// make sure it is in the repository
|
||||||
|
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
|
||||||
|
.getQueryEngine()
|
||||||
|
.getNamedQueryRepository()
|
||||||
|
.getResultSetMappingMemento( "name" );
|
||||||
|
assertThat( mappingMemento, notNullValue() );
|
||||||
|
|
||||||
|
// apply it to a native-query
|
||||||
|
final String qryString = "select name from SimpleEntityWithNamedMappings";
|
||||||
|
final List<String> names = session.createNativeQuery( qryString, "name" ).list();
|
||||||
|
|
||||||
|
assertThat( names.size(), is( 1 ) );
|
||||||
|
assertThat( names.get( 0 ), is( "test" ) );
|
||||||
|
|
||||||
|
// todo (6.0) : should also try executing the ProcedureCall once that functionality is implemented
|
||||||
|
session.createStoredProcedureCall( "abc", "name" );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompoundScalarMapping(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
// make sure it is in the repository
|
||||||
|
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
|
||||||
|
.getQueryEngine()
|
||||||
|
.getNamedQueryRepository()
|
||||||
|
.getResultSetMappingMemento( "id_name" );
|
||||||
|
assertThat( mappingMemento, notNullValue() );
|
||||||
|
|
||||||
|
// apply it to a native-query
|
||||||
|
final String qryString = "select id, name from SimpleEntityWithNamedMappings";
|
||||||
|
session.createNativeQuery( qryString, "id_name" ).list();
|
||||||
|
|
||||||
|
// todo (6.0) : should also try executing the ProcedureCall once that functionality is implemented
|
||||||
|
session.createStoredProcedureCall( "abc", "id_name" );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,18 +4,13 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.query.named.resultmapping;
|
package org.hibernate.orm.test.query.resultmapping;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
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.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
@ -25,57 +20,7 @@ import static org.hamcrest.Matchers.notNullValue;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@DomainModel( annotatedClasses = SimpleEntityWithNamedMappings.class )
|
public class EntityResultTests extends BaseUsageTest {
|
||||||
@SessionFactory
|
|
||||||
public class UsageTests {
|
|
||||||
// select a.{*}
|
|
||||||
@Test
|
|
||||||
public void testSimpleScalarMapping(SessionFactoryScope scope) {
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
// make sure it is in the repository
|
|
||||||
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
|
|
||||||
.getQueryEngine()
|
|
||||||
.getNamedQueryRepository()
|
|
||||||
.getResultSetMappingMemento( "id_name" );
|
|
||||||
assertThat( mappingMemento, notNullValue() );
|
|
||||||
|
|
||||||
// apply it to a native-query
|
|
||||||
final String qryString = "select id, name from SimpleEntityWithNamedMappings";
|
|
||||||
session.createNativeQuery( qryString, "id_name" ).list();
|
|
||||||
|
|
||||||
// todo (6.0) : should also try executing the ProcedureCall once that functionality is implemented
|
|
||||||
session.createStoredProcedureCall( "abc", "id_name" );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSimpleInstantiationOfScalars(SessionFactoryScope scope) {
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
// make sure it is in the repository
|
|
||||||
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
|
|
||||||
.getQueryEngine()
|
|
||||||
.getNamedQueryRepository()
|
|
||||||
.getResultSetMappingMemento( "id_name_dto" );
|
|
||||||
assertThat( mappingMemento, notNullValue() );
|
|
||||||
|
|
||||||
// apply it to a native-query
|
|
||||||
final String qryString = "select id, name from SimpleEntityWithNamedMappings";
|
|
||||||
final List<SimpleEntityWithNamedMappings.DropDownDto> results
|
|
||||||
= session.createNativeQuery( qryString, "id_name_dto" ).list();
|
|
||||||
assertThat( results.size(), is( 1 ) );
|
|
||||||
|
|
||||||
final SimpleEntityWithNamedMappings.DropDownDto dto = results.get( 0 );
|
|
||||||
assertThat( dto.getId(), is( 1 ) );
|
|
||||||
assertThat( dto.getText(), is( "test" ) );
|
|
||||||
|
|
||||||
// todo (6.0) : should also try executing the ProcedureCall once that functionality is implemented
|
|
||||||
session.createStoredProcedureCall( "abc", "id_name_dto" );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleEntityResultMapping(SessionFactoryScope scope) {
|
public void testSimpleEntityResultMapping(SessionFactoryScope scope) {
|
||||||
|
@ -90,8 +35,9 @@ public class UsageTests {
|
||||||
|
|
||||||
// apply it to a native-query
|
// apply it to a native-query
|
||||||
final String qryString = "select id, name, notes from SimpleEntityWithNamedMappings";
|
final String qryString = "select id, name, notes from SimpleEntityWithNamedMappings";
|
||||||
final List<SimpleEntityWithNamedMappings> results
|
final List<SimpleEntityWithNamedMappings> results = session
|
||||||
= session.createNativeQuery( qryString, "entity" ).list();
|
.createNativeQuery( qryString, "entity" )
|
||||||
|
.list();
|
||||||
assertThat( results.size(), is( 1 ) );
|
assertThat( results.size(), is( 1 ) );
|
||||||
|
|
||||||
final SimpleEntityWithNamedMappings entity = results.get( 0 );
|
final SimpleEntityWithNamedMappings entity = results.get( 0 );
|
||||||
|
@ -104,20 +50,60 @@ public class UsageTests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@Test
|
||||||
public void prepareData(SessionFactoryScope scope) {
|
public void testImplicitAttributeMapping(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
session.save( new SimpleEntityWithNamedMappings( 1, "test" ) );
|
// make sure it is in the repository
|
||||||
|
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
|
||||||
|
.getQueryEngine()
|
||||||
|
.getNamedQueryRepository()
|
||||||
|
.getResultSetMappingMemento(
|
||||||
|
"entity-none" );
|
||||||
|
assertThat( mappingMemento, notNullValue() );
|
||||||
|
|
||||||
|
// apply it to a native-query
|
||||||
|
final String qryString = "select id, name, notes from SimpleEntityWithNamedMappings";
|
||||||
|
final List<SimpleEntityWithNamedMappings> results = session
|
||||||
|
.createNativeQuery( qryString, "entity-none" )
|
||||||
|
.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-none" );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@Test
|
||||||
public void cleanUpData(SessionFactoryScope scope) {
|
public void testMixedAttributeMapping(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
session.createQuery( "delete SimpleEntityWithNamedMappings" ).executeUpdate();
|
// make sure it is in the repository
|
||||||
|
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
|
||||||
|
.getQueryEngine()
|
||||||
|
.getNamedQueryRepository()
|
||||||
|
.getResultSetMappingMemento(
|
||||||
|
"entity-id-notes" );
|
||||||
|
assertThat( mappingMemento, notNullValue() );
|
||||||
|
|
||||||
|
// apply it to a native-query
|
||||||
|
final String qryString = "select id, name, notes from SimpleEntityWithNamedMappings";
|
||||||
|
final List<SimpleEntityWithNamedMappings> results = session
|
||||||
|
.createNativeQuery( qryString, "entity-id-notes" )
|
||||||
|
.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-id-notes" );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.query.resultmapping;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class InstantiationResultTests extends BaseUsageTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimpleInstantiationOfScalars(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
// make sure it is in the repository
|
||||||
|
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
|
||||||
|
.getQueryEngine()
|
||||||
|
.getNamedQueryRepository()
|
||||||
|
.getResultSetMappingMemento(
|
||||||
|
"id_name_dto" );
|
||||||
|
assertThat( mappingMemento, notNullValue() );
|
||||||
|
|
||||||
|
// apply it to a native-query
|
||||||
|
final String qryString = "select id, name from SimpleEntityWithNamedMappings";
|
||||||
|
final List<?> results = session.createNativeQuery( qryString, "id_name_dto" ).list();
|
||||||
|
assertThat( results.size(), is( 1 ) );
|
||||||
|
|
||||||
|
final SimpleEntityWithNamedMappings.DropDownDto dto =
|
||||||
|
(SimpleEntityWithNamedMappings.DropDownDto) results.get( 0 );
|
||||||
|
|
||||||
|
assertThat( dto.getId(), is( 1 ) );
|
||||||
|
assertThat( dto.getText(), is( "test" ) );
|
||||||
|
|
||||||
|
// todo (6.0) : should also try executing the ProcedureCall once that functionality is implemented
|
||||||
|
session.createStoredProcedureCall( "abc", "id_name_dto" );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.query.named.resultmapping;
|
package org.hibernate.orm.test.query.resultmapping;
|
||||||
|
|
||||||
import javax.persistence.Basic;
|
import javax.persistence.Basic;
|
||||||
import javax.persistence.ColumnResult;
|
import javax.persistence.ColumnResult;
|
||||||
|
@ -51,6 +51,12 @@ import javax.persistence.SqlResultSetMapping;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@SqlResultSetMapping(
|
||||||
|
name = "entity-none",
|
||||||
|
entities = @EntityResult(
|
||||||
|
entityClass = SimpleEntityWithNamedMappings.class
|
||||||
|
)
|
||||||
|
)
|
||||||
@SqlResultSetMapping(
|
@SqlResultSetMapping(
|
||||||
name = "entity-id-notes",
|
name = "entity-id-notes",
|
||||||
entities = @EntityResult(
|
entities = @EntityResult(
|
|
@ -4,12 +4,13 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.query.named.resultmapping;
|
package org.hibernate.orm.test.query.resultmapping;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||||
import org.hibernate.query.named.NamedQueryRepository;
|
import org.hibernate.query.named.NamedQueryRepository;
|
||||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
|
import org.hibernate.query.results.ResultBuilderBasicValued;
|
||||||
import org.hibernate.query.results.ResultSetMapping;
|
import org.hibernate.query.results.ResultSetMapping;
|
||||||
import org.hibernate.query.results.ResultSetMappingImpl;
|
import org.hibernate.query.results.ResultSetMappingImpl;
|
||||||
import org.hibernate.query.spi.QueryEngine;
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
|
@ -19,6 +20,7 @@ import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
|
@ -43,8 +45,15 @@ public class SimpleNamedMappingTests {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mappingMemento.resolve( mapping, querySpace -> {}, resolutionContext );
|
mappingMemento.resolve( mapping, querySpace -> {
|
||||||
|
}, resolutionContext );
|
||||||
|
|
||||||
assertThat( mapping.getNumberOfResultBuilders(), is( 1 ) );
|
assertThat( mapping.getNumberOfResultBuilders(), is( 1 ) );
|
||||||
|
mapping.visitResultBuilders(
|
||||||
|
(position, builder) -> {
|
||||||
|
assertThat( position, is( 0 ) );
|
||||||
|
assertThat( builder, instanceOf( ResultBuilderBasicValued.class ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue