ResultSet mapping
- support for dynamic instantiations of scalar values. This is all JPA defines support for wrt `@ConstructorResult` - support for mixed result mappings, including dynamic instantiations which JPA says is not legal. We support this in HQL also
This commit is contained in:
parent
8db9709408
commit
bcf995f84f
|
@ -7,8 +7,11 @@
|
||||||
package org.hibernate.boot.query;
|
package org.hibernate.boot.query;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.persistence.ColumnResult;
|
import javax.persistence.ColumnResult;
|
||||||
|
import javax.persistence.ConstructorResult;
|
||||||
|
import javax.persistence.EntityResult;
|
||||||
import javax.persistence.SqlResultSetMapping;
|
import javax.persistence.SqlResultSetMapping;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
@ -17,7 +20,11 @@ import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl;
|
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl;
|
||||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
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.ScalarResultBuilder;
|
||||||
|
import org.hibernate.query.results.StandardInstantiationResultBuilder;
|
||||||
import org.hibernate.query.results.StandardScalarResultBuilder;
|
import org.hibernate.query.results.StandardScalarResultBuilder;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
|
@ -43,38 +50,51 @@ public class SqlResultSetMappingDefinition implements NamedResultSetMappingDefin
|
||||||
public static SqlResultSetMappingDefinition from(
|
public static SqlResultSetMappingDefinition from(
|
||||||
SqlResultSetMapping mappingAnnotation,
|
SqlResultSetMapping mappingAnnotation,
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
if ( mappingAnnotation.classes().length > 0 ) {
|
|
||||||
throw new NotYetImplementedFor6Exception(
|
|
||||||
"Support for dynamic-instantiation result mappings not yet implemented"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( mappingAnnotation.entities().length > 0 ) {
|
|
||||||
throw new NotYetImplementedFor6Exception(
|
|
||||||
"Support for entity result mappings not yet implemented"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( mappingAnnotation.columns().length == 0 ) {
|
|
||||||
throw new NotYetImplementedFor6Exception( "Should never get here" );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
final List<EntityResultMapping> entityResultMappings;
|
||||||
|
final List<ConstructorResultMapping> constructorResultMappings;
|
||||||
final List<JpaColumnResultMapping> columnResultMappings;
|
final List<JpaColumnResultMapping> columnResultMappings;
|
||||||
if ( mappingAnnotation.columns().length == 0 ) {
|
|
||||||
columnResultMappings = null;
|
final EntityResult[] entityResults = mappingAnnotation.entities();
|
||||||
|
if ( entityResults.length > 0 ) {
|
||||||
|
entityResultMappings = Collections.emptyList();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
columnResultMappings = new ArrayList<>( mappingAnnotation.columns().length );
|
entityResultMappings = new ArrayList<>( entityResults.length );
|
||||||
for ( int i = 0; i < mappingAnnotation.columns().length; i++ ) {
|
for ( int i = 0; i < entityResults.length; i++ ) {
|
||||||
final ColumnResult columnMapping = mappingAnnotation.columns()[i];
|
final EntityResult entityResult = entityResults[i];
|
||||||
columnResultMappings.add(
|
entityResultMappings.add( EntityResultMapping.from( entityResult, context ) );
|
||||||
new JpaColumnResultMapping( columnMapping.name(), columnMapping.type() )
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
|
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(
|
return new SqlResultSetMappingDefinition(
|
||||||
mappingAnnotation.name(),
|
mappingAnnotation.name(),
|
||||||
|
entityResultMappings,
|
||||||
|
constructorResultMappings,
|
||||||
columnResultMappings,
|
columnResultMappings,
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
|
@ -82,13 +102,19 @@ public class SqlResultSetMappingDefinition implements NamedResultSetMappingDefin
|
||||||
|
|
||||||
private final String mappingName;
|
private final String mappingName;
|
||||||
|
|
||||||
|
private final List<EntityResultMapping> entityResultMappings;
|
||||||
|
private final List<ConstructorResultMapping> constructorResultMappings;
|
||||||
private final List<JpaColumnResultMapping> columnResultMappings;
|
private final List<JpaColumnResultMapping> columnResultMappings;
|
||||||
|
|
||||||
private SqlResultSetMappingDefinition(
|
private SqlResultSetMappingDefinition(
|
||||||
String mappingName,
|
String mappingName,
|
||||||
|
List<EntityResultMapping> entityResultMappings,
|
||||||
|
List<ConstructorResultMapping> constructorResultMappings,
|
||||||
List<JpaColumnResultMapping> columnResultMappings,
|
List<JpaColumnResultMapping> columnResultMappings,
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
this.mappingName = mappingName;
|
this.mappingName = mappingName;
|
||||||
|
this.entityResultMappings = entityResultMappings;
|
||||||
|
this.constructorResultMappings = constructorResultMappings;
|
||||||
this.columnResultMappings = columnResultMappings;
|
this.columnResultMappings = columnResultMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +125,19 @@ public class SqlResultSetMappingDefinition implements NamedResultSetMappingDefin
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NamedResultSetMappingMemento resolve(SessionFactoryImplementor factory) {
|
public NamedResultSetMappingMemento resolve(SessionFactoryImplementor factory) {
|
||||||
final List<ScalarResultBuilder> scalarResultBuilders = new ArrayList<>();
|
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++ ) {
|
for ( int i = 0; i < columnResultMappings.size(); i++ ) {
|
||||||
final JpaColumnResultMapping resultMapping = columnResultMappings.get( i );
|
final JpaColumnResultMapping resultMapping = columnResultMappings.get( i );
|
||||||
scalarResultBuilders.add( resultMapping.resolve( factory ) );
|
scalarResultBuilders.add( resultMapping.resolve( factory ) );
|
||||||
|
@ -108,6 +145,8 @@ public class SqlResultSetMappingDefinition implements NamedResultSetMappingDefin
|
||||||
|
|
||||||
return new NamedResultSetMappingMementoImpl(
|
return new NamedResultSetMappingMementoImpl(
|
||||||
mappingName,
|
mappingName,
|
||||||
|
entityResultBuilders,
|
||||||
|
instantiationResultBuilders,
|
||||||
scalarResultBuilders,
|
scalarResultBuilders,
|
||||||
factory
|
factory
|
||||||
);
|
);
|
||||||
|
@ -128,6 +167,10 @@ public class SqlResultSetMappingDefinition implements NamedResultSetMappingDefin
|
||||||
: explicitJavaType;
|
: explicitJavaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JpaColumnResultMapping from(ColumnResult columnResult, MetadataBuildingContext context) {
|
||||||
|
return new JpaColumnResultMapping( columnResult.name(), columnResult.type() );
|
||||||
|
}
|
||||||
|
|
||||||
public String getColumnName() {
|
public String getColumnName() {
|
||||||
return columnName;
|
return columnName;
|
||||||
}
|
}
|
||||||
|
@ -151,4 +194,68 @@ public class SqlResultSetMappingDefinition implements NamedResultSetMappingDefin
|
||||||
return new StandardScalarResultBuilder( columnName );
|
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() );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,15 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.internal;
|
package org.hibernate.query.internal;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
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.ResultSetMapping;
|
||||||
import org.hibernate.query.results.ScalarResultBuilder;
|
import org.hibernate.query.results.ScalarResultBuilder;
|
||||||
|
|
||||||
|
@ -22,14 +26,24 @@ import org.hibernate.query.results.ScalarResultBuilder;
|
||||||
public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMemento {
|
public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMemento {
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
private final List<ScalarResultBuilder> scalarResultBuilders;
|
private final List<ResultBuilder> resultBuilders;
|
||||||
|
|
||||||
public NamedResultSetMappingMementoImpl(
|
public NamedResultSetMappingMementoImpl(
|
||||||
String name,
|
String name,
|
||||||
|
List<EntityResultBuilder> entityResultBuilders,
|
||||||
|
List<InstantiationResultBuilder> instantiationResultBuilders,
|
||||||
List<ScalarResultBuilder> scalarResultBuilders,
|
List<ScalarResultBuilder> scalarResultBuilders,
|
||||||
SessionFactoryImplementor factory) {
|
SessionFactoryImplementor factory) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.scalarResultBuilders = scalarResultBuilders;
|
|
||||||
|
final int totalNumberOfBuilders = entityResultBuilders.size()
|
||||||
|
+ instantiationResultBuilders.size()
|
||||||
|
+ scalarResultBuilders.size();
|
||||||
|
this.resultBuilders = new ArrayList<>( totalNumberOfBuilders );
|
||||||
|
|
||||||
|
resultBuilders.addAll( entityResultBuilders );
|
||||||
|
resultBuilders.addAll( instantiationResultBuilders );
|
||||||
|
resultBuilders.addAll( scalarResultBuilders );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -42,16 +56,6 @@ public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMe
|
||||||
ResultSetMapping resultSetMapping,
|
ResultSetMapping resultSetMapping,
|
||||||
Consumer<String> querySpaceConsumer,
|
Consumer<String> querySpaceConsumer,
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
scalarResultBuilders.forEach(
|
resultBuilders.forEach( resultSetMapping::addResultBuilder );
|
||||||
builder -> resultSetMapping.addResultBuilder(
|
|
||||||
(jdbcResultsMetadata, legacyFetchResolver, sqlSelectionConsumer, sessionFactory1) ->
|
|
||||||
builder.buildReturn(
|
|
||||||
jdbcResultsMetadata,
|
|
||||||
legacyFetchResolver,
|
|
||||||
sqlSelectionConsumer,
|
|
||||||
sessionFactory
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nominal extension to ResultBuilder for cases involving dynamic-instantiation results
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface InstantiationResultBuilder extends ResultBuilder {
|
||||||
|
}
|
|
@ -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.results;
|
||||||
|
|
||||||
|
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.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
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 StandardInstantiationResultBuilder implements InstantiationResultBuilder {
|
||||||
|
private final JavaTypeDescriptor<?> javaTypeDescriptor;
|
||||||
|
private final List<ResultBuilder> argumentResultBuilders;
|
||||||
|
|
||||||
|
public StandardInstantiationResultBuilder(
|
||||||
|
JavaTypeDescriptor<?> javaTypeDescriptor,
|
||||||
|
List<ResultBuilder> argumentResultBuilders) {
|
||||||
|
this.javaTypeDescriptor = javaTypeDescriptor;
|
||||||
|
this.argumentResultBuilders = argumentResultBuilders;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResult<?> buildReturn(
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||||
|
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
final List<ArgumentDomainResult<?>> argumentDomainResults = new ArrayList<>( argumentResultBuilders.size() );
|
||||||
|
|
||||||
|
argumentResultBuilders.forEach(
|
||||||
|
argumentResultBuilder -> argumentDomainResults.add(
|
||||||
|
new ArgumentDomainResult<>(
|
||||||
|
argumentResultBuilder.buildReturn( jdbcResultsMetadata, legacyFetchResolver, sqlSelectionConsumer, sessionFactory )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
return new DynamicInstantiationResultImpl(
|
||||||
|
null,
|
||||||
|
DynamicInstantiationNature.CLASS,
|
||||||
|
javaTypeDescriptor,
|
||||||
|
argumentDomainResults
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -155,10 +155,11 @@ public class NativeQueryImpl<R>
|
||||||
SharedSessionContractImplementor session) {
|
SharedSessionContractImplementor session) {
|
||||||
this( memento, session );
|
this( memento, session );
|
||||||
|
|
||||||
// todo (6.0) : need to add handling for `javax.persistence.NamedNativeQuery#resultSetMapping`
|
session.getFactory()
|
||||||
// and `javax.persistence.NamedNativeQuery#resultClass`
|
.getQueryEngine()
|
||||||
|
.getNamedQueryRepository()
|
||||||
// todo (6.0) : relatedly, does `resultSetMappingName` come from `NamedNativeQuery#resultSetMapping`?
|
.getResultSetMappingMemento( resultSetMappingName )
|
||||||
|
.resolve( resultSetMapping, (s) -> {}, getSessionFactory() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public NativeQueryImpl(
|
public NativeQueryImpl(
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.orm.test.query.named.resultmapping;
|
package org.hibernate.orm.test.query.named.resultmapping;
|
||||||
|
|
||||||
import javax.persistence.ColumnResult;
|
import javax.persistence.ColumnResult;
|
||||||
|
import javax.persistence.ConstructorResult;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.SqlResultSetMapping;
|
import javax.persistence.SqlResultSetMapping;
|
||||||
|
@ -26,6 +27,16 @@ import javax.persistence.SqlResultSetMapping;
|
||||||
@ColumnResult( name = "name" )
|
@ColumnResult( name = "name" )
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@SqlResultSetMapping(
|
||||||
|
name = "id_name_dto",
|
||||||
|
classes = @ConstructorResult(
|
||||||
|
targetClass = SimpleEntityWithNamedMappings.DropDownDto.class,
|
||||||
|
columns = {
|
||||||
|
@ColumnResult( name = "id" ),
|
||||||
|
@ColumnResult( name = "name" )
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
public class SimpleEntityWithNamedMappings {
|
public class SimpleEntityWithNamedMappings {
|
||||||
@Id
|
@Id
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
@ -55,4 +66,22 @@ public class SimpleEntityWithNamedMappings {
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class DropDownDto {
|
||||||
|
private final Integer id;
|
||||||
|
private final String text;
|
||||||
|
|
||||||
|
public DropDownDto(Integer id, String text) {
|
||||||
|
this.id = id;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.query.named.resultmapping;
|
package org.hibernate.orm.test.query.named.resultmapping;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
|
||||||
|
|
||||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
|
||||||
import org.hibernate.testing.orm.domain.helpdesk.Incident;
|
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
@ -20,32 +17,60 @@ import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
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.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.notNullValue;
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@DomainModel( standardModels = StandardDomainModel.HELPDESK )
|
@DomainModel( annotatedClasses = SimpleEntityWithNamedMappings.class )
|
||||||
@SessionFactory
|
@SessionFactory
|
||||||
public class UsageTests {
|
public class UsageTests {
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleScalarMappings(SessionFactoryScope scope) {
|
public void testSimpleScalarMapping(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
// make sure it is in the repository
|
// make sure it is in the repository
|
||||||
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
|
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
|
||||||
.getQueryEngine()
|
.getQueryEngine()
|
||||||
.getNamedQueryRepository()
|
.getNamedQueryRepository()
|
||||||
.getResultSetMappingMemento( "incident_summary" );
|
.getResultSetMappingMemento( "id_name" );
|
||||||
assertThat( mappingMemento, notNullValue() );
|
assertThat( mappingMemento, notNullValue() );
|
||||||
|
|
||||||
// apply it to a native-query
|
// apply it to a native-query
|
||||||
final String qryString = "select id, description, reported from incident";
|
final String qryString = "select id, name from SimpleEntityWithNamedMappings";
|
||||||
session.createNativeQuery( qryString, "incident_summary" ).list();
|
session.createNativeQuery( qryString, "id_name" ).list();
|
||||||
|
|
||||||
// todo (6.0) : should also try executing the ProcedureCall once that functionality is implemented
|
// todo (6.0) : should also try executing the ProcedureCall once that functionality is implemented
|
||||||
session.createStoredProcedureCall( "abc", "incident_summary" );
|
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" );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -54,7 +79,7 @@ public class UsageTests {
|
||||||
public void prepareData(SessionFactoryScope scope) {
|
public void prepareData(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
session.save( new Incident( 1, "test", Instant.now() ) );
|
session.save( new SimpleEntityWithNamedMappings( 1, "test" ) );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -63,7 +88,7 @@ public class UsageTests {
|
||||||
public void cleanUpData(SessionFactoryScope scope) {
|
public void cleanUpData(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
session.createQuery( "delete Incident" ).executeUpdate();
|
session.createQuery( "delete SimpleEntityWithNamedMappings" ).executeUpdate();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue