HHH-18450 Handle array result types for multi-valued parameters

Also fix an NPE in SqmSelectionQueryImpl#determineResultType
This commit is contained in:
Marco Belladelli 2024-08-12 10:16:59 +02:00
parent 7893d1066f
commit 3521857ef2
2 changed files with 16 additions and 9 deletions

View File

@ -63,6 +63,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelection;
import org.hibernate.sql.results.internal.TupleMetadata; import org.hibernate.sql.results.internal.TupleMetadata;
import org.hibernate.sql.results.spi.ResultsConsumer; import org.hibernate.sql.results.spi.ResultsConsumer;
import org.hibernate.sql.results.spi.SingleResultConsumer; import org.hibernate.sql.results.spi.SingleResultConsumer;
import org.hibernate.type.descriptor.java.JavaType;
import static org.hibernate.jpa.HibernateHints.HINT_CACHEABLE; import static org.hibernate.jpa.HibernateHints.HINT_CACHEABLE;
import static org.hibernate.jpa.HibernateHints.HINT_CACHE_MODE; import static org.hibernate.jpa.HibernateHints.HINT_CACHE_MODE;
@ -276,15 +277,15 @@ public class SqmSelectionQueryImpl<R> extends AbstractSqmSelectionQuery<R>
return Object[].class; return Object[].class;
} }
else { else {
final SqmSelection<?> selection = selections.get(0); final SqmSelection<?> selection = selections.get( 0 );
if ( isSelectionAssignableToResultType( selection, expectedResultType ) ) { if ( isSelectionAssignableToResultType( selection, expectedResultType ) ) {
return selection.getNodeJavaType().getJavaTypeClass(); final JavaType<?> nodeJavaType = selection.getNodeJavaType();
} if ( nodeJavaType != null ) {
else { return nodeJavaType.getJavaTypeClass();
// let's assume there's some }
// way to instantiate it
return expectedResultType;
} }
// let's assume there's some way to instantiate it
return expectedResultType;
} }
} }
else if ( expectedResultType != null ) { else if ( expectedResultType != null ) {

View File

@ -43,6 +43,7 @@ import org.hibernate.metamodel.model.domain.SimpleDomainType;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.metamodel.model.domain.internal.EntitySqmPathSource; import org.hibernate.metamodel.model.domain.internal.EntitySqmPathSource;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.BindableType;
import org.hibernate.query.IllegalQueryOperationException; import org.hibernate.query.IllegalQueryOperationException;
import org.hibernate.query.IllegalSelectQueryException; import org.hibernate.query.IllegalSelectQueryException;
import org.hibernate.query.Order; import org.hibernate.query.Order;
@ -827,10 +828,15 @@ public class SqmUtil {
} }
public static boolean isSelectionAssignableToResultType(SqmSelection<?> selection, Class<?> expectedResultType) { public static boolean isSelectionAssignableToResultType(SqmSelection<?> selection, Class<?> expectedResultType) {
if ( expectedResultType == null if ( expectedResultType == null ) {
|| selection != null && selection.getSelectableNode() instanceof SqmParameter ) {
return true; return true;
} }
else if ( selection != null && selection.getSelectableNode() instanceof SqmParameter<?> sqmParameter ) {
final Class<?> anticipatedClass = sqmParameter.getAnticipatedType() != null ?
sqmParameter.getAnticipatedType().getBindableJavaType() :
null;
return anticipatedClass != null && expectedResultType.isAssignableFrom( anticipatedClass );
}
else if ( selection == null else if ( selection == null
|| !isHqlTuple( selection ) && selection.getSelectableNode().isCompoundSelection() ) { || !isHqlTuple( selection ) && selection.getSelectableNode().isCompoundSelection() ) {
return false; return false;