HHH-15930 - Support scalar resultClass in @NamedNativeQuery

This commit is contained in:
Steve Ebersole 2022-12-22 15:48:16 -06:00
parent 501d3869d4
commit 263768d5c5
8 changed files with 139 additions and 59 deletions

View File

@ -11,6 +11,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import jakarta.persistence.CascadeType; import jakarta.persistence.CascadeType;
import jakarta.persistence.ColumnResult; import jakarta.persistence.ColumnResult;
import jakarta.persistence.ConstructorResult; import jakarta.persistence.ConstructorResult;
@ -41,7 +42,8 @@ import jakarta.persistence.Version;
name = "find_person_name", name = "find_person_name",
query = query =
"SELECT name " + "SELECT name " +
"FROM Person " "FROM Person ",
resultClass = String.class
) )
//end::sql-scalar-NamedNativeQuery-example[] //end::sql-scalar-NamedNativeQuery-example[]
//tag::sql-multiple-scalar-values-NamedNativeQuery-example[] //tag::sql-multiple-scalar-values-NamedNativeQuery-example[]

View File

@ -9,14 +9,13 @@ package org.hibernate.userguide.sql;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import jakarta.persistence.PersistenceException;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
import org.hibernate.loader.NonUniqueDiscoveredSqlAliasException; import org.hibernate.loader.NonUniqueDiscoveredSqlAliasException;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.TupleTransformer; import org.hibernate.query.TupleTransformer;
import org.hibernate.transform.Transformers; import org.hibernate.transform.Transformers;
@ -38,6 +37,9 @@ import org.hibernate.testing.TestForIssue;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import jakarta.persistence.PersistenceException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -586,7 +588,7 @@ public class SQLTest extends BaseEntityManagerFunctionalTestCase {
doInJPA(this::entityManagerFactory, entityManager -> { doInJPA(this::entityManagerFactory, entityManager -> {
//tag::sql-jpa-scalar-named-query-example[] //tag::sql-jpa-scalar-named-query-example[]
List<String> names = entityManager.createNamedQuery( List<String> names = entityManager.createNamedQuery(
"find_person_name") "find_person_name", String.class)
.getResultList(); .getResultList();
//end::sql-jpa-scalar-named-query-example[] //end::sql-jpa-scalar-named-query-example[]
assertEquals(3, names.size()); assertEquals(3, names.size());
@ -611,7 +613,7 @@ public class SQLTest extends BaseEntityManagerFunctionalTestCase {
doInJPA(this::entityManagerFactory, entityManager -> { doInJPA(this::entityManagerFactory, entityManager -> {
//tag::sql-jpa-multiple-scalar-values-named-query-example[] //tag::sql-jpa-multiple-scalar-values-named-query-example[]
List<Object[]> tuples = entityManager.createNamedQuery( List<Object[]> tuples = entityManager.createNamedQuery(
"find_person_name_and_nickName") "find_person_name_and_nickName", Object[].class)
.getResultList(); .getResultList();
for(Object[] tuple : tuples) { for(Object[] tuple : tuples) {
@ -646,10 +648,12 @@ public class SQLTest extends BaseEntityManagerFunctionalTestCase {
doInJPA(this::entityManagerFactory, entityManager -> { doInJPA(this::entityManagerFactory, entityManager -> {
//tag::sql-jpa-multiple-scalar-values-dto-named-query-example[] //tag::sql-jpa-multiple-scalar-values-dto-named-query-example[]
List<PersonNames> personNames = entityManager.createNamedQuery( List<PersonNames> personNames = entityManager.createNamedQuery(
"find_person_name_and_nickName_dto") "find_person_name_and_nickName_dto", PersonNames.class)
.getResultList(); .getResultList();
//end::sql-jpa-multiple-scalar-values-dto-named-query-example[] //end::sql-jpa-multiple-scalar-values-dto-named-query-example[]
assertEquals(3, personNames.size()); assertEquals(3, personNames.size());
assertThat( personNames.get(0) ).isNotNull();
assertThat( personNames.get(0) ).isInstanceOf(PersonNames.class);
}); });
} }
@ -686,11 +690,13 @@ public class SQLTest extends BaseEntityManagerFunctionalTestCase {
doInJPA(this::entityManagerFactory, entityManager -> { doInJPA(this::entityManagerFactory, entityManager -> {
//tag::sql-jpa-entity-named-query-example[] //tag::sql-jpa-entity-named-query-example[]
List<Person> persons = entityManager.createNamedQuery( List<Person> persons = entityManager.createNamedQuery(
"find_person_by_name") "find_person_by_name", Person.class)
.setParameter("name", "J%") .setParameter("name", "J%")
.getResultList(); .getResultList();
//end::sql-jpa-entity-named-query-example[] //end::sql-jpa-entity-named-query-example[]
assertEquals(1, persons.size()); assertEquals(1, persons.size());
assertThat( persons ).hasSize( 1 );
assertThat( persons.get( 0 ) ).isInstanceOf( Person.class );
}); });
} }
@ -716,7 +722,7 @@ public class SQLTest extends BaseEntityManagerFunctionalTestCase {
doInJPA(this::entityManagerFactory, entityManager -> { doInJPA(this::entityManagerFactory, entityManager -> {
//tag::sql-jpa-entity-associations_named-query-example[] //tag::sql-jpa-entity-associations_named-query-example[]
List<Object[]> tuples = entityManager.createNamedQuery( List<Object[]> tuples = entityManager.createNamedQuery(
"find_person_with_phones_by_name") "find_person_with_phones_by_name", Object[].class)
.setParameter("name", "J%") .setParameter("name", "J%")
.getResultList(); .getResultList();
@ -726,6 +732,7 @@ public class SQLTest extends BaseEntityManagerFunctionalTestCase {
} }
//end::sql-jpa-entity-associations_named-query-example[] //end::sql-jpa-entity-associations_named-query-example[]
assertEquals(1, tuples.size()); assertEquals(1, tuples.size());
assertThat( tuples.get(0).getClass().isArray() ).isTrue();
}); });
} }
@ -756,7 +763,7 @@ public class SQLTest extends BaseEntityManagerFunctionalTestCase {
doInJPA(this::entityManagerFactory, entityManager -> { doInJPA(this::entityManagerFactory, entityManager -> {
//tag::sql-jpa-composite-key-entity-associations_named-query-example[] //tag::sql-jpa-composite-key-entity-associations_named-query-example[]
List<Object[]> tuples = entityManager.createNamedQuery( List<Object[]> tuples = entityManager.createNamedQuery(
"find_all_spaceships") "find_all_spaceships", Object[].class)
.getResultList(); .getResultList();
for(Object[] tuple : tuples) { for(Object[] tuple : tuples) {

View File

@ -21,6 +21,7 @@ import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.mapping.internal.DiscriminatedAssociationAttributeMapping; import org.hibernate.metamodel.mapping.internal.DiscriminatedAssociationAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart; import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.NativeQuery; import org.hibernate.query.NativeQuery;
import org.hibernate.query.internal.ResultSetMappingResolutionContext; import org.hibernate.query.internal.ResultSetMappingResolutionContext;
@ -40,6 +41,7 @@ import org.hibernate.query.results.implicit.ImplicitFetchBuilderEntity;
import org.hibernate.query.results.implicit.ImplicitFetchBuilderEntityPart; import org.hibernate.query.results.implicit.ImplicitFetchBuilderEntityPart;
import org.hibernate.query.results.implicit.ImplicitFetchBuilderPlural; import org.hibernate.query.results.implicit.ImplicitFetchBuilderPlural;
import org.hibernate.query.results.implicit.ImplicitModelPartResultBuilderEntity; import org.hibernate.query.results.implicit.ImplicitModelPartResultBuilderEntity;
import org.hibernate.query.results.implicit.ImplicitResultClassBuilder;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Fetchable;
@ -241,14 +243,23 @@ public class Builders {
return new DynamicFetchBuilderLegacy( tableAlias, ownerTableAlias, joinPropertyName, new ArrayList<>(), new HashMap<>() ); return new DynamicFetchBuilderLegacy( tableAlias, ownerTableAlias, joinPropertyName, new ArrayList<>(), new HashMap<>() );
} }
public static ResultBuilder implicitEntityResultBuilder( public static ResultBuilder resultClassBuilder(
Class<?> resultMappingClass, Class<?> resultMappingClass,
ResultSetMappingResolutionContext resolutionContext) { ResultSetMappingResolutionContext resolutionContext) {
final EntityMappingType entityMappingType = resolutionContext final MappingMetamodelImplementor mappingMetamodel = resolutionContext
.getSessionFactory() .getSessionFactory()
.getRuntimeMetamodels() .getRuntimeMetamodels()
.getEntityMappingType( resultMappingClass ); .getMappingMetamodel();
return new ImplicitModelPartResultBuilderEntity( entityMappingType ); final EntityMappingType entityMappingType = mappingMetamodel.findEntityDescriptor( resultMappingClass );
if ( entityMappingType != null ) {
// the resultClass is an entity
return new ImplicitModelPartResultBuilderEntity( entityMappingType );
}
// todo : support for known embeddables might be nice
// otherwise, assume it's a "basic" mapping
return new ImplicitResultClassBuilder( resultMappingClass );
} }
public static ImplicitFetchBuilder implicitFetchBuilder( public static ImplicitFetchBuilder implicitFetchBuilder(

View File

@ -0,0 +1,70 @@
/*
* 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.implicit;
import java.util.function.BiFunction;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import org.hibernate.type.BasicType;
import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.NamedNativeQuery;
/**
* ResultBuilder for handling {@link NamedNativeQuery#resultClass()} when the
* class does not refer to an entity
*
* @author Steve Ebersole
*/
public class ImplicitResultClassBuilder implements ResultBuilder {
private final Class<?> suppliedResultClass;
public ImplicitResultClassBuilder(Class<?> suppliedResultClass) {
this.suppliedResultClass = suppliedResultClass;
}
@Override
public DomainResult<?> buildResult(
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
DomainResultCreationState domainResultCreationState) {
final MappingMetamodelImplementor mappingMetamodel = domainResultCreationState.getSqlAstCreationState()
.getCreationContext()
.getMappingMetamodel();
final TypeConfiguration typeConfiguration = mappingMetamodel.getTypeConfiguration();
final int jdbcResultPosition = resultPosition + 1;
final BasicType<Object> basicType = jdbcResultsMetadata.resolveType(
jdbcResultPosition,
typeConfiguration.getJavaTypeRegistry().resolveDescriptor( suppliedResultClass ),
typeConfiguration
);
return new BasicResult<>(
resultPosition,
jdbcResultsMetadata.resolveColumnName( jdbcResultPosition ),
basicType
);
}
@Override
public Class<?> getJavaType() {
return suppliedResultClass;
}
@Override
public ResultBuilder cacheKeyInstance() {
return this;
}
}

View File

@ -20,8 +20,6 @@ import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -31,7 +29,6 @@ import org.hibernate.MappingException;
import org.hibernate.QueryException; import org.hibernate.QueryException;
import org.hibernate.ScrollMode; import org.hibernate.ScrollMode;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.query.spi.NativeQueryInterpreter; import org.hibernate.engine.query.spi.NativeQueryInterpreter;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -92,6 +89,8 @@ import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeReference; import org.hibernate.type.BasicTypeReference;
import jakarta.persistence.AttributeConverter; import jakarta.persistence.AttributeConverter;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.FlushModeType; import jakarta.persistence.FlushModeType;
@ -103,6 +102,7 @@ import jakarta.persistence.Tuple;
import jakarta.persistence.metamodel.SingularAttribute; import jakarta.persistence.metamodel.SingularAttribute;
import static org.hibernate.jpa.HibernateHints.HINT_NATIVE_LOCK_MODE; import static org.hibernate.jpa.HibernateHints.HINT_NATIVE_LOCK_MODE;
import static org.hibernate.query.results.Builders.resultClassBuilder;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -157,7 +157,7 @@ public class NativeQueryImpl<R>
if ( memento.getResultMappingClass() != null ) { if ( memento.getResultMappingClass() != null ) {
resultSetMapping.addResultBuilder( resultSetMapping.addResultBuilder(
Builders.implicitEntityResultBuilder( resultClassBuilder(
memento.getResultMappingClass(), memento.getResultMappingClass(),
context context
) )
@ -239,36 +239,18 @@ public class NativeQueryImpl<R>
} }
if ( memento.getResultMappingClass() != null ) { if ( memento.getResultMappingClass() != null ) {
resultSetMapping.addResultBuilder( resultSetMapping.addResultBuilder( resultClassBuilder(
Builders.implicitEntityResultBuilder( memento.getResultMappingClass(),
memento.getResultMappingClass(), context
context ) );
)
);
return true; return true;
} }
// if ( resultJavaType != null && resultJavaType != Tuple.class ) {
// todo (6.0): in 5.x we didn't add implicit result builders and by doing so, if ( resultJavaType != null && resultJavaType != Tuple.class && !resultJavaType.isArray() ) {
// the result type check at the end of the constructor will fail like in 5.x // todo : allow the expected Java type imply a builder to use
// final JpaMetamodel jpaMetamodel = context.getSessionFactory().getJpaMetamodel(); // resultSetMapping.addResultBuilder( resultClassBuilder( resultJavaType, context ) );
// if ( jpaMetamodel.findEntityType( resultJavaType ) != null ) {
// resultSetMapping.addResultBuilder(
// Builders.implicitEntityResultBuilder( resultJavaType, context )
// );
// }
// else {
// resultSetMapping.addResultBuilder(
// Builders.scalar(
// 1,
// context.getSessionFactory()
// .getTypeConfiguration()
// .getBasicTypeForJavaType( resultJavaType )
// )
// );
// }
//
// return true; // return true;
// } }
return false; return false;
}, },
@ -281,8 +263,9 @@ public class NativeQueryImpl<R>
else if ( resultJavaType != null && resultJavaType != Object[].class ) { else if ( resultJavaType != null && resultJavaType != Object[].class ) {
switch ( resultSetMapping.getNumberOfResultBuilders() ) { switch ( resultSetMapping.getNumberOfResultBuilders() ) {
case 0: case 0:
throw new IllegalArgumentException( "Named query exists but its result type is not compatible" ); throw new IllegalArgumentException( "Named query exists, but did not specify a resultClass" );
case 1: case 1:
// would be nice to support types that are "wrappable", as in `JavaType#wrap`
final Class<?> actualResultJavaType = resultSetMapping.getResultBuilders().get( 0 ).getJavaType(); final Class<?> actualResultJavaType = resultSetMapping.getResultBuilders().get( 0 ).getJavaType();
if ( actualResultJavaType != null && !resultJavaType.isAssignableFrom( actualResultJavaType ) ) { if ( actualResultJavaType != null && !resultJavaType.isAssignableFrom( actualResultJavaType ) ) {
throw buildIncompatibleException( resultJavaType, actualResultJavaType ); throw buildIncompatibleException( resultJavaType, actualResultJavaType );

View File

@ -64,6 +64,7 @@ import org.hibernate.sql.results.spi.ScrollableResultsConsumer;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.CacheRetrieveMode; import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode; import jakarta.persistence.CacheStoreMode;
@ -565,14 +566,14 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor {
public <J> BasicType<J> resolveType( public <J> BasicType<J> resolveType(
int position, int position,
JavaType<J> explicitJavaType, JavaType<J> explicitJavaType,
SessionFactoryImplementor sessionFactory) { TypeConfiguration typeConfiguration) {
if ( columnNames == null ) { if ( columnNames == null ) {
initializeArrays(); initializeArrays();
} }
final BasicType<J> basicType = resultSetAccess.resolveType( final BasicType<J> basicType = resultSetAccess.resolveType(
position, position,
explicitJavaType, explicitJavaType,
sessionFactory typeConfiguration
); );
types[position - 1] = basicType; types[position - 1] = basicType;
return basicType; return basicType;
@ -622,7 +623,7 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor {
public <J> BasicType<J> resolveType( public <J> BasicType<J> resolveType(
int position, int position,
JavaType<J> explicitJavaType, JavaType<J> explicitJavaType,
SessionFactoryImplementor sessionFactory) { TypeConfiguration typeConfiguration) {
final BasicType<?> type = types[position - 1]; final BasicType<?> type = types[position - 1];
if ( type == null ) { if ( type == null ) {
throw new IllegalStateException( "Unexpected resolving of unavailable column at position: " + position ); throw new IllegalStateException( "Unexpected resolving of unavailable column at position: " + position );
@ -632,7 +633,7 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor {
return (BasicType<J>) type; return (BasicType<J>) type;
} }
else { else {
return sessionFactory.getTypeConfiguration().getBasicTypeRegistry().resolve( return typeConfiguration.getBasicTypeRegistry().resolve(
explicitJavaType, explicitJavaType,
type.getJdbcType() type.getJdbcType()
); );

View File

@ -10,8 +10,6 @@ import java.sql.ResultSet;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import jakarta.persistence.EnumType;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -22,6 +20,8 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.EnumType;
/** /**
* Access to a JDBC ResultSet and information about it. * Access to a JDBC ResultSet and information about it.
* *
@ -72,11 +72,7 @@ public interface ResultSetAccess extends JdbcValuesMetadata {
} }
@Override @Override
default <J> BasicType<J> resolveType( default <J> BasicType<J> resolveType(int position, JavaType<J> explicitJavaType, TypeConfiguration typeConfiguration) {
int position,
JavaType<J> explicitJavaType,
SessionFactoryImplementor sessionFactory) {
final TypeConfiguration typeConfiguration = getFactory().getTypeConfiguration();
final JdbcServices jdbcServices = getFactory().getJdbcServices(); final JdbcServices jdbcServices = getFactory().getJdbcServices();
try { try {
final ResultSetMetaData metaData = getResultSet().getMetaData(); final ResultSetMetaData metaData = getResultSet().getMetaData();

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.results.jdbc.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.spi.TypeConfiguration;
/** /**
* Access to information about the underlying JDBC values * Access to information about the underlying JDBC values
@ -31,11 +32,20 @@ public interface JdbcValuesMetadata {
String resolveColumnName(int position); String resolveColumnName(int position);
/** /**
* The basic type of a particular result value by position * Determine the mapping to use for a particular position in the result
*/
default <J> BasicType<J> resolveType(
int position,
JavaType<J> explicitJavaType,
SessionFactoryImplementor sessionFactory) {
return resolveType( position, explicitJavaType, sessionFactory.getTypeConfiguration() );
}
/**
* Determine the mapping to use for a particular position in the result
*/ */
<J> BasicType<J> resolveType( <J> BasicType<J> resolveType(
int position, int position,
JavaType<J> explicitJavaType, JavaType<J> explicitJavaType,
SessionFactoryImplementor sessionFactory); TypeConfiguration typeConfiguration);
} }