HHH-15078 - Support for Tuple and SelectionQuery
This commit is contained in:
parent
88938ac482
commit
aa0c57aa5c
|
@ -86,6 +86,10 @@ import static org.hibernate.jpa.QueryHints.HINT_READONLY;
|
|||
public abstract class AbstractSelectionQuery<R>
|
||||
extends AbstractCommonQueryContract
|
||||
implements SelectionQuery<R>, DomainQueryExecutionContext {
|
||||
/**
|
||||
* The value used for {@link #getQueryString} for Criteria-based queries
|
||||
*/
|
||||
public static final String CRITERIA_HQL_STRING = "<criteria>";
|
||||
|
||||
private Callback callback;
|
||||
|
||||
|
@ -189,10 +193,17 @@ public abstract class AbstractSelectionQuery<R>
|
|||
}
|
||||
}
|
||||
|
||||
protected abstract String getQueryString();
|
||||
|
||||
/**
|
||||
* Used during handling of Criteria queries
|
||||
*/
|
||||
protected void visitQueryReturnType(
|
||||
SqmQueryPart<R> queryPart,
|
||||
Class<R> resultType,
|
||||
SessionFactoryImplementor factory) {
|
||||
assert getQueryString().equals( CRITERIA_HQL_STRING );
|
||||
|
||||
if ( queryPart instanceof SqmQuerySpec<?> ) {
|
||||
final SqmQuerySpec<R> sqmQuerySpec = (SqmQuerySpec<R>) queryPart;
|
||||
final List<SqmSelection<?>> sqmSelections = sqmQuerySpec.getSelectClause().getSelections();
|
||||
|
|
|
@ -119,11 +119,6 @@ import static org.hibernate.query.sqm.internal.SqmUtil.isSelect;
|
|||
public class QuerySqmImpl<R>
|
||||
extends AbstractSelectionQuery<R>
|
||||
implements SqmQueryImplementor<R>, InterpretationsKeySource, DomainQueryExecutionContext {
|
||||
|
||||
/**
|
||||
* The value used for {@link #getQueryString} for Criteria-based queries
|
||||
*/
|
||||
public static final String CRITERIA_HQL_STRING = "<criteria>";
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QuerySqmImpl.class );
|
||||
|
||||
private final String hql;
|
||||
|
|
|
@ -18,6 +18,7 @@ import jakarta.persistence.FlushModeType;
|
|||
import jakarta.persistence.LockModeType;
|
||||
import jakarta.persistence.Parameter;
|
||||
import jakarta.persistence.TemporalType;
|
||||
import jakarta.persistence.Tuple;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
|
@ -78,8 +79,6 @@ import static org.hibernate.query.spi.SqlOmittingQueryOptions.omitSqlQueryOption
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implements SqmSelectionQuery<R>, InterpretationsKeySource {
|
||||
public static final String CRITERIA_HQL_STRING = "<criteria>";
|
||||
|
||||
private final String hql;
|
||||
private final SqmSelectStatement<R> sqm;
|
||||
|
||||
|
@ -105,14 +104,19 @@ public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implemen
|
|||
this.domainParameterXref = hqlInterpretation.getDomainParameterXref();
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||
|
||||
visitQueryReturnType( sqm.getQueryPart(), expectedResultType, getSessionFactory() );
|
||||
// visitQueryReturnType( sqm.getQueryPart(), expectedResultType, getSessionFactory() );
|
||||
this.resultType = determineResultType( sqm, expectedResultType );
|
||||
|
||||
setComment( hql );
|
||||
this.tupleMetadata = null;
|
||||
this.tupleMetadata = buildTupleMetadata( sqm, expectedResultType );
|
||||
}
|
||||
|
||||
private static <T> Class<T> determineResultType(SqmSelectStatement<?> sqm, Class<?> expectedResultType) {
|
||||
if ( expectedResultType != null && expectedResultType.equals( Tuple.class ) ) {
|
||||
//noinspection unchecked
|
||||
return (Class<T>) Tuple.class;
|
||||
}
|
||||
|
||||
if ( expectedResultType == null || ! expectedResultType.isArray() ) {
|
||||
final List<SqmSelection<?>> selections = sqm.getQuerySpec().getSelectClause().getSelections();
|
||||
if ( selections.size() == 1 ) {
|
||||
|
@ -152,10 +156,9 @@ public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implemen
|
|||
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||
|
||||
visitQueryReturnType( sqm.getQueryPart(), resultType, getSessionFactory() );
|
||||
setComment( hql );
|
||||
|
||||
applyOptions( memento );
|
||||
|
||||
this.tupleMetadata = buildTupleMetadata( sqm, resultType );
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.query.sqm;
|
||||
|
||||
import java.util.List;
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.NamedQuery;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Tuple;
|
||||
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
|
@ -22,8 +24,10 @@ import org.hibernate.testing.orm.domain.contacts.Contact;
|
|||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
|
@ -63,6 +67,54 @@ public class BasicSelectionQueryTests {
|
|||
} );
|
||||
}
|
||||
|
||||
private void createDummyEntity(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
session.persist( new DummyEntity( 1, "whatever" ) );
|
||||
} );
|
||||
}
|
||||
|
||||
private final String tuple_selection_hql = "select c.id as id, c.name as name from DummyEntity c";
|
||||
|
||||
@Test
|
||||
public void tupleSelectionTestBaseline(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
checkResults( session.createQuery( tuple_selection_hql, Tuple.class ), session );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tupleSelectionTest(SessionFactoryScope scope) {
|
||||
createDummyEntity( scope );
|
||||
|
||||
// first make sure we get back the correct results via list
|
||||
scope.inTransaction( (session) -> {
|
||||
final SelectionQuery<Tuple> selectionQuery = session.createSelectionQuery( tuple_selection_hql, Tuple.class );
|
||||
|
||||
final List<Tuple> tuples = selectionQuery.list();
|
||||
assertThat( tuples ).hasSize( 1 );
|
||||
|
||||
assertThat( tuples.get( 0 ) ).isInstanceOf( Tuple.class );
|
||||
final Tuple tuple = tuples.get( 0 );
|
||||
assertThat( tuple.get( 0 ) ).isEqualTo( 1 );
|
||||
assertThat( tuple.get( "id" ) ).isEqualTo( 1 );
|
||||
assertThat( tuple.get( 1 ) ).isEqualTo( "whatever" );
|
||||
assertThat( tuple.get( "name" ) ).isEqualTo( "whatever" );
|
||||
} );
|
||||
|
||||
// next make sure the rest of the execution methods work
|
||||
scope.inTransaction( (session) -> {
|
||||
final SelectionQuery<Tuple> selectionQuery = session.createSelectionQuery( tuple_selection_hql, Tuple.class );
|
||||
checkResults( selectionQuery, session );
|
||||
} );
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void dropTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
session.createMutationQuery( "delete DummyEntity" ).executeUpdate();
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rawScalarSelectTest(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
|
|
Loading…
Reference in New Issue