HHH-17598 Allow array typed queries without result wrapping

This commit is contained in:
Marco Belladelli 2024-01-10 10:45:56 +01:00 committed by Christian Beikov
parent 2f60e08c64
commit f8d84f9f7f
2 changed files with 53 additions and 36 deletions

View File

@ -195,18 +195,18 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
return new MySqmJdbcExecutionContextAdapter( executionContext, jdbcSelect, subSelectFetchKeyHandler, hql );
}
private static Class<?> singleSelectionType(SqmSelectStatement<?> sqm) {
private static SqmSelection<?> singleSelection(SqmSelectStatement<?> sqm) {
final List<SqmSelection<?>> selections = sqm.getQueryPart()
.getFirstQuerySpec()
.getSelectClause()
.getSelections();
if ( selections.size() == 1 ) {
final SqmSelection<?> sqmSelection = selections.get( 0 );
return sqmSelection.getSelectableNode().isCompoundSelection() ?
null :
sqmSelection.getNodeJavaType().getJavaTypeClass();
return selections.size() == 1 ? selections.get( 0 ) : null;
}
return null;
private static Class<?> selectionType(SqmSelection<?> selection) {
return selection != null && !selection.getSelectableNode().isCompoundSelection() ?
selection.getNodeJavaType().getJavaTypeClass()
: null;
}
@SuppressWarnings("unchecked")
@ -221,10 +221,12 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
else if ( resultType == null ) {
return RowTransformerStandardImpl.instance();
}
else if ( resultType == Object[].class ) {
else {
final SqmSelection<?> selection = singleSelection( sqm );
if ( resultType.isArray() && resultType != selectionType( selection ) ) {
return (RowTransformer<T>) RowTransformerArrayImpl.instance();
}
else if ( resultType == List.class && resultType != singleSelectionType( sqm ) ) {
else if ( resultType == List.class && resultType != selectionType( selection ) ) {
return (RowTransformer<T>) RowTransformerListImpl.instance();
}
else {
@ -233,7 +235,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
// 2) an explicit result-type, other than an array or List, was specified
if ( tupleMetadata == null ) {
if ( sqm.getQueryPart().getFirstQuerySpec().getSelectClause().getSelections().size() == 1 ) {
if ( selection != null ) {
return RowTransformerSingularReturnImpl.instance();
}
else {
@ -256,6 +258,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
}
}
}
}
private static <T> RowTransformer<T> makeRowTransformerTupleTransformerAdapter(
SqmSelectStatement<?> sqm,

View File

@ -47,7 +47,7 @@ public class ConvertedListAttributeQueryTest {
@Test
@SuppressWarnings( "rawtypes" )
public void testHQL(SessionFactoryScope scope) {
public void testListHQL(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final List resultList = session.createQuery(
"select emp.phoneNumbers from Employee emp where emp.id = :EMP_ID",
@ -59,7 +59,7 @@ public class ConvertedListAttributeQueryTest {
@Test
@SuppressWarnings( "rawtypes" )
public void testCriteria(SessionFactoryScope scope) {
public void testListCriteria(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final CriteriaBuilder cb = session.getCriteriaBuilder();
final CriteriaQuery<List> q = cb.createQuery( List.class );
@ -71,6 +71,20 @@ public class ConvertedListAttributeQueryTest {
} );
}
@Test
public void testArrayCriteria(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final CriteriaBuilder cb = session.getCriteriaBuilder();
final CriteriaQuery<Integer[]> q = cb.createQuery( Integer[].class );
final Root<Employee> r = q.from( Employee.class );
q.multiselect( r.get( "id" ), r.get( "id" ) );
q.where( cb.equal( r.get( "id" ), 1 ) );
final Object result = session.createQuery( q ).getSingleResult();
assertThat( result ).isInstanceOf( Object[].class );
assertThat( ( (Object[]) result ) ).containsExactly( 1, 1 );
} );
}
@Entity( name = "Employee" )
public static class Employee {
@Id