Skip to content

Commit a060a3b

Browse files
mbelladebeikov
authored andcommitted
HHH-17598 Allow array typed queries without result wrapping
1 parent e5a2b3e commit a060a3b

File tree

2 files changed

+53
-36
lines changed

2 files changed

+53
-36
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/internal/ConcreteSqmSelectQueryPlan.java

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -195,18 +195,18 @@ protected static SqmJdbcExecutionContextAdapter listInterpreterExecutionContext(
195195
return new MySqmJdbcExecutionContextAdapter( executionContext, jdbcSelect, subSelectFetchKeyHandler, hql );
196196
}
197197

198-
private static Class<?> singleSelectionType(SqmSelectStatement<?> sqm) {
198+
private static SqmSelection<?> singleSelection(SqmSelectStatement<?> sqm) {
199199
final List<SqmSelection<?>> selections = sqm.getQueryPart()
200200
.getFirstQuerySpec()
201201
.getSelectClause()
202202
.getSelections();
203-
if ( selections.size() == 1 ) {
204-
final SqmSelection<?> sqmSelection = selections.get( 0 );
205-
return sqmSelection.getSelectableNode().isCompoundSelection() ?
206-
null :
207-
sqmSelection.getNodeJavaType().getJavaTypeClass();
208-
}
209-
return null;
203+
return selections.size() == 1 ? selections.get( 0 ) : null;
204+
}
205+
206+
private static Class<?> selectionType(SqmSelection<?> selection) {
207+
return selection != null && !selection.getSelectableNode().isCompoundSelection() ?
208+
selection.getNodeJavaType().getJavaTypeClass()
209+
: null;
210210
}
211211

212212
@SuppressWarnings("unchecked")
@@ -221,37 +221,40 @@ protected static <T> RowTransformer<T> determineRowTransformer(
221221
else if ( resultType == null ) {
222222
return RowTransformerStandardImpl.instance();
223223
}
224-
else if ( resultType == Object[].class ) {
225-
return (RowTransformer<T>) RowTransformerArrayImpl.instance();
226-
}
227-
else if ( resultType == List.class && resultType != singleSelectionType( sqm ) ) {
228-
return (RowTransformer<T>) RowTransformerListImpl.instance();
229-
}
230224
else {
231-
// NOTE : if we get here :
232-
// 1) there is no TupleTransformer specified
233-
// 2) an explicit result-type, other than an array or List, was specified
234-
235-
if ( tupleMetadata == null ) {
236-
if ( sqm.getQueryPart().getFirstQuerySpec().getSelectClause().getSelections().size() == 1 ) {
237-
return RowTransformerSingularReturnImpl.instance();
238-
}
239-
else {
240-
throw new AssertionFailure( "Query defined multiple selections, should have had TupleMetadata" );
241-
}
225+
final SqmSelection<?> selection = singleSelection( sqm );
226+
if ( resultType.isArray() && resultType != selectionType( selection ) ) {
227+
return (RowTransformer<T>) RowTransformerArrayImpl.instance();
228+
}
229+
else if ( resultType == List.class && resultType != selectionType( selection ) ) {
230+
return (RowTransformer<T>) RowTransformerListImpl.instance();
242231
}
243232
else {
244-
if ( Tuple.class.equals( resultType ) ) {
245-
return (RowTransformer<T>) new RowTransformerJpaTupleImpl( tupleMetadata );
246-
}
247-
else if ( Map.class.equals( resultType ) ) {
248-
return (RowTransformer<T>) new RowTransformerMapImpl( tupleMetadata );
249-
}
250-
else if ( isClass( resultType ) ) {
251-
return new RowTransformerConstructorImpl<>( resultType, tupleMetadata );
233+
// NOTE : if we get here :
234+
// 1) there is no TupleTransformer specified
235+
// 2) an explicit result-type, other than an array or List, was specified
236+
237+
if ( tupleMetadata == null ) {
238+
if ( selection != null ) {
239+
return RowTransformerSingularReturnImpl.instance();
240+
}
241+
else {
242+
throw new AssertionFailure( "Query defined multiple selections, should have had TupleMetadata" );
243+
}
252244
}
253245
else {
254-
throw new InstantiationException( "Query result type is not instantiable", resultType );
246+
if ( Tuple.class.equals( resultType ) ) {
247+
return (RowTransformer<T>) new RowTransformerJpaTupleImpl( tupleMetadata );
248+
}
249+
else if ( Map.class.equals( resultType ) ) {
250+
return (RowTransformer<T>) new RowTransformerMapImpl( tupleMetadata );
251+
}
252+
else if ( isClass( resultType ) ) {
253+
return new RowTransformerConstructorImpl<>( resultType, tupleMetadata );
254+
}
255+
else {
256+
throw new InstantiationException( "Query result type is not instantiable", resultType );
257+
}
255258
}
256259
}
257260
}

hibernate-core/src/test/java/org/hibernate/orm/test/mapping/converted/converter/ConvertedListAttributeQueryTest.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public void tearDown(SessionFactoryScope scope) {
4747

4848
@Test
4949
@SuppressWarnings( "rawtypes" )
50-
public void testHQL(SessionFactoryScope scope) {
50+
public void testListHQL(SessionFactoryScope scope) {
5151
scope.inTransaction( session -> {
5252
final List resultList = session.createQuery(
5353
"select emp.phoneNumbers from Employee emp where emp.id = :EMP_ID",
@@ -59,7 +59,7 @@ public void testHQL(SessionFactoryScope scope) {
5959

6060
@Test
6161
@SuppressWarnings( "rawtypes" )
62-
public void testCriteria(SessionFactoryScope scope) {
62+
public void testListCriteria(SessionFactoryScope scope) {
6363
scope.inTransaction( session -> {
6464
final CriteriaBuilder cb = session.getCriteriaBuilder();
6565
final CriteriaQuery<List> q = cb.createQuery( List.class );
@@ -71,6 +71,20 @@ public void testCriteria(SessionFactoryScope scope) {
7171
} );
7272
}
7373

74+
@Test
75+
public void testArrayCriteria(SessionFactoryScope scope) {
76+
scope.inTransaction( session -> {
77+
final CriteriaBuilder cb = session.getCriteriaBuilder();
78+
final CriteriaQuery<Integer[]> q = cb.createQuery( Integer[].class );
79+
final Root<Employee> r = q.from( Employee.class );
80+
q.multiselect( r.get( "id" ), r.get( "id" ) );
81+
q.where( cb.equal( r.get( "id" ), 1 ) );
82+
final Object result = session.createQuery( q ).getSingleResult();
83+
assertThat( result ).isInstanceOf( Object[].class );
84+
assertThat( ( (Object[]) result ) ).containsExactly( 1, 1 );
85+
} );
86+
}
87+
7488
@Entity( name = "Employee" )
7589
public static class Employee {
7690
@Id

0 commit comments

Comments
 (0)