HHH-15930 - Support scalar resultClass in @NamedNativeQuery
This commit is contained in:
parent
501d3869d4
commit
263768d5c5
|
@ -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[]
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 );
|
||||||
|
|
|
@ -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()
|
||||||
);
|
);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue