HHH-17598 Allow array typed queries without result wrapping
This commit is contained in:
parent
e5a2b3ec0b
commit
a060a3b9c0
|
@ -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 null;
|
||||
return selections.size() == 1 ? selections.get( 0 ) : null;
|
||||
}
|
||||
|
||||
private static Class<?> selectionType(SqmSelection<?> selection) {
|
||||
return selection != null && !selection.getSelectableNode().isCompoundSelection() ?
|
||||
selection.getNodeJavaType().getJavaTypeClass()
|
||||
: null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -221,37 +221,40 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
|
|||
else if ( resultType == null ) {
|
||||
return RowTransformerStandardImpl.instance();
|
||||
}
|
||||
else if ( resultType == Object[].class ) {
|
||||
return (RowTransformer<T>) RowTransformerArrayImpl.instance();
|
||||
}
|
||||
else if ( resultType == List.class && resultType != singleSelectionType( sqm ) ) {
|
||||
return (RowTransformer<T>) RowTransformerListImpl.instance();
|
||||
}
|
||||
else {
|
||||
// NOTE : if we get here :
|
||||
// 1) there is no TupleTransformer specified
|
||||
// 2) an explicit result-type, other than an array or List, was specified
|
||||
|
||||
if ( tupleMetadata == null ) {
|
||||
if ( sqm.getQueryPart().getFirstQuerySpec().getSelectClause().getSelections().size() == 1 ) {
|
||||
return RowTransformerSingularReturnImpl.instance();
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Query defined multiple selections, should have had TupleMetadata" );
|
||||
}
|
||||
final SqmSelection<?> selection = singleSelection( sqm );
|
||||
if ( resultType.isArray() && resultType != selectionType( selection ) ) {
|
||||
return (RowTransformer<T>) RowTransformerArrayImpl.instance();
|
||||
}
|
||||
else if ( resultType == List.class && resultType != selectionType( selection ) ) {
|
||||
return (RowTransformer<T>) RowTransformerListImpl.instance();
|
||||
}
|
||||
else {
|
||||
if ( Tuple.class.equals( resultType ) ) {
|
||||
return (RowTransformer<T>) new RowTransformerJpaTupleImpl( tupleMetadata );
|
||||
}
|
||||
else if ( Map.class.equals( resultType ) ) {
|
||||
return (RowTransformer<T>) new RowTransformerMapImpl( tupleMetadata );
|
||||
}
|
||||
else if ( isClass( resultType ) ) {
|
||||
return new RowTransformerConstructorImpl<>( resultType, tupleMetadata );
|
||||
// NOTE : if we get here :
|
||||
// 1) there is no TupleTransformer specified
|
||||
// 2) an explicit result-type, other than an array or List, was specified
|
||||
|
||||
if ( tupleMetadata == null ) {
|
||||
if ( selection != null ) {
|
||||
return RowTransformerSingularReturnImpl.instance();
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Query defined multiple selections, should have had TupleMetadata" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new InstantiationException( "Query result type is not instantiable", resultType );
|
||||
if ( Tuple.class.equals( resultType ) ) {
|
||||
return (RowTransformer<T>) new RowTransformerJpaTupleImpl( tupleMetadata );
|
||||
}
|
||||
else if ( Map.class.equals( resultType ) ) {
|
||||
return (RowTransformer<T>) new RowTransformerMapImpl( tupleMetadata );
|
||||
}
|
||||
else if ( isClass( resultType ) ) {
|
||||
return new RowTransformerConstructorImpl<>( resultType, tupleMetadata );
|
||||
}
|
||||
else {
|
||||
throw new InstantiationException( "Query result type is not instantiable", resultType );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue