HHH-17779 support for key-based pagination
This commit is contained in:
parent
2f4a6ebcaf
commit
4fbcfbdaba
|
@ -13,7 +13,6 @@ import org.hibernate.Incubating;
|
||||||
import org.hibernate.graph.GraphSemantic;
|
import org.hibernate.graph.GraphSemantic;
|
||||||
import org.hibernate.graph.spi.AppliedGraph;
|
import org.hibernate.graph.spi.AppliedGraph;
|
||||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||||
import org.hibernate.internal.util.NullnessUtil;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ import java.util.Set;
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
import org.hibernate.ConnectionAcquisitionMode;
|
import org.hibernate.ConnectionAcquisitionMode;
|
||||||
import org.hibernate.FetchNotFoundException;
|
import org.hibernate.FetchNotFoundException;
|
||||||
import org.hibernate.Filter;
|
|
||||||
import org.hibernate.FlushMode;
|
import org.hibernate.FlushMode;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.Interceptor;
|
import org.hibernate.Interceptor;
|
||||||
|
|
|
@ -29,7 +29,6 @@ import org.hibernate.loader.ast.spi.Loadable;
|
||||||
import org.hibernate.loader.ast.spi.Loader;
|
import org.hibernate.loader.ast.spi.Loader;
|
||||||
import org.hibernate.metamodel.CollectionClassification;
|
import org.hibernate.metamodel.CollectionClassification;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.Collections.unmodifiableList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for pagination based on a unique key of the result
|
||||||
|
* set instead of the {@link Page#getFirstResult() offset}.
|
||||||
|
*
|
||||||
|
* @since 6.5
|
||||||
|
*
|
||||||
|
* @author Gavin King
|
||||||
|
*/
|
||||||
|
public class KeyedPage<R> {
|
||||||
|
private final List<Order<? super R>> keyDefinition;
|
||||||
|
private final Page page;
|
||||||
|
private final List<Comparable<?>> key;
|
||||||
|
|
||||||
|
KeyedPage(List<Order<? super R>> keyDefinition, Page page) {
|
||||||
|
this( keyDefinition, page, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyedPage(List<Order<? super R>> keyDefinition, Page page, List<Comparable<?>> key) {
|
||||||
|
this.page = page;
|
||||||
|
this.keyDefinition = unmodifiableList(keyDefinition);
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Order<? super R>> getKeyDefinition() {
|
||||||
|
return keyDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Page getPage() {
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null key indicates that the {@linkplain Page#getNumber() page number}
|
||||||
|
* should be used. This is useful to obtain an initial page of results.
|
||||||
|
*/
|
||||||
|
public List<Comparable<?>> getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,8 @@ package org.hibernate.query;
|
||||||
|
|
||||||
import org.hibernate.Incubating;
|
import org.hibernate.Incubating;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifies a page of query results by {@linkplain #size page size}
|
* Identifies a page of query results by {@linkplain #size page size}
|
||||||
* and {@linkplain #number page number}.
|
* and {@linkplain #number page number}.
|
||||||
|
@ -50,7 +52,7 @@ public class Page {
|
||||||
return size*number;
|
return size*number;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Page(int size, int number) {
|
Page(int size, int number) {
|
||||||
if ( size <= 0 ) {
|
if ( size <= 0 ) {
|
||||||
throw new IllegalArgumentException("page size must be strictly positive");
|
throw new IllegalArgumentException("page size must be strictly positive");
|
||||||
}
|
}
|
||||||
|
@ -83,4 +85,8 @@ public class Page {
|
||||||
public Page first() {
|
public Page first() {
|
||||||
return first( size );
|
return first( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <R> KeyedPage<R> keyedBy(List<Order<? super R>> keyDefinition) {
|
||||||
|
return new KeyedPage<>( keyDefinition, this );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -903,6 +903,11 @@ public interface Query<R> extends SelectionQuery<R>, MutationQuery, TypedQuery<R
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SelectionQuery<R> setPage(KeyedPage<R> page) {
|
||||||
|
throw new UnsupportedOperationException("keyed paging not supported");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Query<R> setHint(String hintName, Object value);
|
Query<R> setHint(String hintName, Object value);
|
||||||
|
|
||||||
|
|
|
@ -395,6 +395,16 @@ public interface SelectionQuery<R> extends CommonQueryContract {
|
||||||
@Incubating
|
@Incubating
|
||||||
SelectionQuery<R> setPage(Page page);
|
SelectionQuery<R> setPage(Page page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the {@linkplain KeyedPage keyed page} of results to return.
|
||||||
|
*
|
||||||
|
* @see KeyedPage
|
||||||
|
*
|
||||||
|
* @since 6.5
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
SelectionQuery<R> setPage(KeyedPage<R> page);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain the {@link CacheMode} in effect for this query. By default,
|
* Obtain the {@link CacheMode} in effect for this query. By default,
|
||||||
* the query inherits the {@link CacheMode} of the session from which
|
* the query inherits the {@link CacheMode} of the session from which
|
||||||
|
|
|
@ -6,22 +6,40 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.internal;
|
package org.hibernate.query.sqm.internal;
|
||||||
|
|
||||||
|
import jakarta.persistence.criteria.Expression;
|
||||||
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.graph.spi.AppliedGraph;
|
import org.hibernate.graph.spi.AppliedGraph;
|
||||||
|
import org.hibernate.query.IllegalQueryOperationException;
|
||||||
|
import org.hibernate.query.IllegalSelectQueryException;
|
||||||
|
import org.hibernate.query.KeyedPage;
|
||||||
|
import org.hibernate.query.Order;
|
||||||
|
import org.hibernate.query.Page;
|
||||||
import org.hibernate.query.QueryLogging;
|
import org.hibernate.query.QueryLogging;
|
||||||
|
import org.hibernate.query.SelectionQuery;
|
||||||
|
import org.hibernate.query.criteria.JpaSelection;
|
||||||
import org.hibernate.query.hql.internal.QuerySplitter;
|
import org.hibernate.query.hql.internal.QuerySplitter;
|
||||||
import org.hibernate.query.spi.AbstractSelectionQuery;
|
import org.hibernate.query.spi.AbstractSelectionQuery;
|
||||||
import org.hibernate.query.spi.MutableQueryOptions;
|
import org.hibernate.query.spi.MutableQueryOptions;
|
||||||
import org.hibernate.query.spi.QueryOptions;
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.query.spi.SelectQueryPlan;
|
import org.hibernate.query.spi.SelectQueryPlan;
|
||||||
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
|
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||||
|
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
|
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||||
|
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||||
|
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
import org.hibernate.sql.results.internal.TupleMetadata;
|
import org.hibernate.sql.results.internal.TupleMetadata;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
import static org.hibernate.cfg.QuerySettings.FAIL_ON_PAGINATION_OVER_COLLECTION_FETCH;
|
import static org.hibernate.cfg.QuerySettings.FAIL_ON_PAGINATION_OVER_COLLECTION_FETCH;
|
||||||
|
import static org.hibernate.query.sqm.internal.SqmUtil.sortSpecification;
|
||||||
|
import static org.hibernate.query.sqm.tree.SqmCopyContext.noParamCopyContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
|
@ -73,8 +91,115 @@ abstract class AbstractSqmSelectionQuery<R> extends AbstractSelectionQuery<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract SqmStatement<R> getSqmStatement();
|
public abstract SqmStatement<R> getSqmStatement();
|
||||||
|
protected abstract void setSqmStatement(SqmSelectStatement<R> statement);
|
||||||
public abstract DomainParameterXref getDomainParameterXref();
|
public abstract DomainParameterXref getDomainParameterXref();
|
||||||
public abstract TupleMetadata getTupleMetadata();
|
public abstract TupleMetadata getTupleMetadata();
|
||||||
|
|
||||||
|
private SqmSelectStatement<R> getSqmSelectStatement() {
|
||||||
|
final SqmStatement<R> sqmStatement = getSqmStatement();
|
||||||
|
if ( sqmStatement instanceof SqmSelectStatement ) {
|
||||||
|
return (SqmSelectStatement<R>) sqmStatement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalSelectQueryException( "Not a select query" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SelectionQuery<R> setOrder(List<Order<? super R>> orderList) {
|
||||||
|
SqmSelectStatement<R> sqm = getSqmSelectStatement();
|
||||||
|
sqm = sqm.copy( noParamCopyContext() );
|
||||||
|
final SqmSelectStatement<R> select = sqm;
|
||||||
|
sqm.orderBy( orderList.stream().map( order -> sortSpecification( select, order ) )
|
||||||
|
.collect( toList() ) );
|
||||||
|
// TODO: when the QueryInterpretationCache can handle caching criteria queries,
|
||||||
|
// simply cache the new SQM as if it were a criteria query, and remove this:
|
||||||
|
getQueryOptions().setQueryPlanCachingEnabled( false );
|
||||||
|
setSqmStatement( sqm );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SelectionQuery<R> setOrder(Order<? super R> order) {
|
||||||
|
SqmSelectStatement<R> sqm = getSqmSelectStatement();
|
||||||
|
sqm = sqm.copy( noParamCopyContext() );
|
||||||
|
sqm.orderBy( sortSpecification( sqm, order ) );
|
||||||
|
// TODO: when the QueryInterpretationCache can handle caching criteria queries,
|
||||||
|
// simply cache the new SQM as if it were a criteria query, and remove this:
|
||||||
|
getQueryOptions().setQueryPlanCachingEnabled( false );
|
||||||
|
setSqmStatement( sqm );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SelectionQuery<R> setPage(Page page) {
|
||||||
|
setMaxResults( page.getMaxResults() );
|
||||||
|
setFirstResult( page.getFirstResult() );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SelectionQuery<R> setPage(KeyedPage<R> page) {
|
||||||
|
setOrder( page.getKeyDefinition() );
|
||||||
|
setMaxResults( page.getPage().getMaxResults() );
|
||||||
|
if ( page.getKey() == null ) {
|
||||||
|
setFirstResult( page.getPage().getFirstResult() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addRestrictions( page.getKeyDefinition(), page.getKey() );
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addRestrictions(List<Order<? super R>> keyDefinition, List<Comparable<?>> keyValues) {
|
||||||
|
SqmSelectStatement<R> sqm = getSqmSelectStatement();
|
||||||
|
sqm = sqm.copy( noParamCopyContext() );
|
||||||
|
final SqmQuerySpec<R> querySpec = sqm.getQuerySpec();
|
||||||
|
final SqmWhereClause whereClause = querySpec.getWhereClause();
|
||||||
|
final List<? extends JpaSelection<?>> items = querySpec.getSelectClause().getSelectionItems();
|
||||||
|
if ( items.size() == 1 ) {
|
||||||
|
final JpaSelection<?> selected = items.get(0);
|
||||||
|
for ( int i = 0; i < keyDefinition.size(); i++ ) {
|
||||||
|
// ordering by an attribute of the returned entity
|
||||||
|
if ( selected instanceof SqmRoot ) {
|
||||||
|
whereClause.applyPredicate( keyPredicate(
|
||||||
|
(SqmFrom<?,?>) selected,
|
||||||
|
keyDefinition.get(i),
|
||||||
|
(Comparable) keyValues.get(i))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalQueryOperationException("Select item was not an entity type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalQueryOperationException("Query has multiple items in the select list");
|
||||||
|
}
|
||||||
|
// TODO: when the QueryInterpretationCache can handle caching criteria queries,
|
||||||
|
// simply cache the new SQM as if it were a criteria query, and remove this:
|
||||||
|
getQueryOptions().setQueryPlanCachingEnabled( false );
|
||||||
|
setSqmStatement( sqm );
|
||||||
|
}
|
||||||
|
|
||||||
|
private <C extends Comparable<? super C>> SqmPredicate keyPredicate(
|
||||||
|
SqmFrom<?, ?> selected, Order<? super R> key, C keyValue) {
|
||||||
|
if ( !key.getEntityClass().isAssignableFrom( selected.getJavaType() ) ) {
|
||||||
|
throw new IllegalQueryOperationException("Select item was of wrong entity type");
|
||||||
|
}
|
||||||
|
final Expression<? extends C> path = selected.get( key.getAttributeName() );
|
||||||
|
final NodeBuilder builder = getSqmStatement().nodeBuilder();
|
||||||
|
switch ( key.getDirection() ) {
|
||||||
|
case ASCENDING:
|
||||||
|
return builder.greaterThan( path, keyValue);
|
||||||
|
case DESCENDING:
|
||||||
|
return builder.lessThan( path, keyValue);
|
||||||
|
default:
|
||||||
|
throw new AssertionFailure("Unrecognized key direction");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Class<R> getExpectedResultType();
|
public abstract Class<R> getExpectedResultType();
|
||||||
|
|
||||||
protected SelectQueryPlan<R> buildSelectQueryPlan() {
|
protected SelectQueryPlan<R> buildSelectQueryPlan() {
|
||||||
|
|
|
@ -47,9 +47,10 @@ import org.hibernate.persister.entity.AbstractEntityPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.BindableType;
|
import org.hibernate.query.BindableType;
|
||||||
import org.hibernate.query.IllegalQueryOperationException;
|
import org.hibernate.query.IllegalQueryOperationException;
|
||||||
import org.hibernate.query.IllegalSelectQueryException;
|
|
||||||
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
|
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
|
||||||
|
import org.hibernate.query.KeyedPage;
|
||||||
import org.hibernate.query.Order;
|
import org.hibernate.query.Order;
|
||||||
|
import org.hibernate.query.Page;
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.query.Query;
|
||||||
import org.hibernate.query.QueryParameter;
|
import org.hibernate.query.QueryParameter;
|
||||||
import org.hibernate.query.ResultListTransformer;
|
import org.hibernate.query.ResultListTransformer;
|
||||||
|
@ -109,7 +110,6 @@ import jakarta.persistence.PersistenceException;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
import org.hibernate.sql.results.spi.SingleResultConsumer;
|
import org.hibernate.sql.results.spi.SingleResultConsumer;
|
||||||
|
|
||||||
import static java.util.stream.Collectors.toList;
|
|
||||||
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;
|
||||||
import static org.hibernate.jpa.HibernateHints.HINT_CACHE_REGION;
|
import static org.hibernate.jpa.HibernateHints.HINT_CACHE_REGION;
|
||||||
|
@ -126,10 +126,8 @@ import static org.hibernate.query.sqm.internal.AppliedGraphs.containsCollectionF
|
||||||
import static org.hibernate.query.sqm.internal.SqmInterpretationsKey.createInterpretationsKey;
|
import static org.hibernate.query.sqm.internal.SqmInterpretationsKey.createInterpretationsKey;
|
||||||
import static org.hibernate.query.sqm.internal.SqmInterpretationsKey.generateNonSelectKey;
|
import static org.hibernate.query.sqm.internal.SqmInterpretationsKey.generateNonSelectKey;
|
||||||
import static org.hibernate.query.sqm.internal.SqmUtil.isSelect;
|
import static org.hibernate.query.sqm.internal.SqmUtil.isSelect;
|
||||||
import static org.hibernate.query.sqm.internal.SqmUtil.sortSpecification;
|
|
||||||
import static org.hibernate.query.sqm.internal.SqmUtil.verifyIsNonSelectStatement;
|
import static org.hibernate.query.sqm.internal.SqmUtil.verifyIsNonSelectStatement;
|
||||||
import static org.hibernate.query.sqm.internal.TypecheckUtil.assertAssignable;
|
import static org.hibernate.query.sqm.internal.TypecheckUtil.assertAssignable;
|
||||||
import static org.hibernate.query.sqm.tree.SqmCopyContext.noParamCopyContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Query} implementation based on an SQM
|
* {@link Query} implementation based on an SQM
|
||||||
|
@ -426,6 +424,11 @@ public class QuerySqmImpl<R>
|
||||||
return sqm;
|
return sqm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setSqmStatement(SqmSelectStatement<R> sqm) {
|
||||||
|
this.sqm = sqm;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DomainParameterXref getDomainParameterXref() {
|
public DomainParameterXref getDomainParameterXref() {
|
||||||
return domainParameterXref;
|
return domainParameterXref;
|
||||||
|
@ -903,36 +906,27 @@ public class QuerySqmImpl<R>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query<R> setOrder(List<Order<? super R>> orderList) {
|
public Query<R> setOrder(Order<? super R> order) {
|
||||||
if ( sqm instanceof SqmSelectStatement ) {
|
super.setOrder(order);
|
||||||
sqm = sqm.copy( noParamCopyContext() );
|
return this;
|
||||||
final SqmSelectStatement<R> select = (SqmSelectStatement<R>) sqm;
|
|
||||||
select.orderBy( orderList.stream().map( order -> sortSpecification( select, order ) )
|
|
||||||
.collect( toList() ) );
|
|
||||||
// TODO: when the QueryInterpretationCache can handle caching criteria queries,
|
|
||||||
// simply cache the new SQM as if it were a criteria query, and remove this:
|
|
||||||
getQueryOptions().setQueryPlanCachingEnabled( false );
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalSelectQueryException( "Not a select query" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query<R> setOrder(Order<? super R> order) {
|
public Query<R> setOrder(List<Order<? super R>> orders) {
|
||||||
if ( sqm instanceof SqmSelectStatement ) {
|
super.setOrder(orders);
|
||||||
sqm = sqm.copy( noParamCopyContext() );
|
return this;
|
||||||
SqmSelectStatement<R> select = (SqmSelectStatement<R>) sqm;
|
}
|
||||||
select.orderBy( sortSpecification( select, order ) );
|
|
||||||
// TODO: when the QueryInterpretationCache can handle caching criteria queries,
|
@Override
|
||||||
// simply cache the new SQM as if it were a criteria query, and remove this:
|
public Query<R> setPage(Page page) {
|
||||||
getQueryOptions().setQueryPlanCachingEnabled( false );
|
super.setPage(page);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw new IllegalSelectQueryException( "Not a select query" );
|
@Override
|
||||||
}
|
public Query<R> setPage(KeyedPage<R> page) {
|
||||||
|
super.setPage(page);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -31,7 +31,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.graph.spi.AppliedGraph;
|
import org.hibernate.graph.spi.AppliedGraph;
|
||||||
import org.hibernate.internal.util.collections.IdentitySet;
|
import org.hibernate.internal.util.collections.IdentitySet;
|
||||||
import org.hibernate.query.BindableType;
|
import org.hibernate.query.BindableType;
|
||||||
import org.hibernate.query.Order;
|
|
||||||
import org.hibernate.query.Page;
|
import org.hibernate.query.Page;
|
||||||
import org.hibernate.query.QueryParameter;
|
import org.hibernate.query.QueryParameter;
|
||||||
import org.hibernate.query.SelectionQuery;
|
import org.hibernate.query.SelectionQuery;
|
||||||
|
@ -63,7 +62,6 @@ 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 static java.util.stream.Collectors.toList;
|
|
||||||
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;
|
||||||
import static org.hibernate.jpa.HibernateHints.HINT_CACHE_REGION;
|
import static org.hibernate.jpa.HibernateHints.HINT_CACHE_REGION;
|
||||||
|
@ -77,7 +75,6 @@ import static org.hibernate.jpa.SpecHints.HINT_SPEC_CACHE_STORE_MODE;
|
||||||
import static org.hibernate.query.spi.SqlOmittingQueryOptions.omitSqlQueryOptions;
|
import static org.hibernate.query.spi.SqlOmittingQueryOptions.omitSqlQueryOptions;
|
||||||
import static org.hibernate.query.sqm.internal.SqmInterpretationsKey.createInterpretationsKey;
|
import static org.hibernate.query.sqm.internal.SqmInterpretationsKey.createInterpretationsKey;
|
||||||
import static org.hibernate.query.sqm.internal.SqmUtil.isSelectionAssignableToResultType;
|
import static org.hibernate.query.sqm.internal.SqmUtil.isSelectionAssignableToResultType;
|
||||||
import static org.hibernate.query.sqm.internal.SqmUtil.sortSpecification;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -245,6 +242,11 @@ public class SqmSelectionQueryImpl<R> extends AbstractSqmSelectionQuery<R>
|
||||||
return sqm;
|
return sqm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setSqmStatement(SqmSelectStatement<R> sqm) {
|
||||||
|
this.sqm = sqm;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DomainParameterXref getDomainParameterXref() {
|
public DomainParameterXref getDomainParameterXref() {
|
||||||
return domainParameterXref;
|
return domainParameterXref;
|
||||||
|
@ -275,34 +277,6 @@ public class SqmSelectionQueryImpl<R> extends AbstractSqmSelectionQuery<R>
|
||||||
// return this;
|
// return this;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@Override
|
|
||||||
public SelectionQuery<R> setPage(Page page) {
|
|
||||||
setMaxResults( page.getMaxResults() );
|
|
||||||
setFirstResult( page.getFirstResult() );
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SelectionQuery<R> setOrder(List<Order<? super R>> orderList) {
|
|
||||||
sqm = sqm.copy( SqmCopyContext.noParamCopyContext() );
|
|
||||||
sqm.orderBy( orderList.stream().map( order -> sortSpecification( sqm, order ) )
|
|
||||||
.collect( toList() ) );
|
|
||||||
// TODO: when the QueryInterpretationCache can handle caching criteria queries,
|
|
||||||
// simply cache the new SQM as if it were a criteria query, and remove this:
|
|
||||||
getQueryOptions().setQueryPlanCachingEnabled( false );
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SelectionQuery<R> setOrder(Order<? super R> order) {
|
|
||||||
sqm = sqm.copy( SqmCopyContext.noParamCopyContext() );
|
|
||||||
sqm.orderBy( sortSpecification( sqm, order ) );
|
|
||||||
// TODO: when the QueryInterpretationCache can handle caching criteria queries,
|
|
||||||
// simply cache the new SQM as if it were a criteria query, and remove this:
|
|
||||||
getQueryOptions().setQueryPlanCachingEnabled( false );
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// execution
|
// execution
|
||||||
|
|
||||||
|
|
|
@ -568,10 +568,12 @@ public class SqmUtil {
|
||||||
final List<SqmSelectableNode<?>> items = sqm.getQuerySpec().getSelectClause().getSelectionItems();
|
final List<SqmSelectableNode<?>> items = sqm.getQuerySpec().getSelectClause().getSelectionItems();
|
||||||
int element = order.getElement();
|
int element = order.getElement();
|
||||||
if ( element < 1) {
|
if ( element < 1) {
|
||||||
throw new IllegalQueryOperationException("Cannot order by element " + element + " (the first select item is element 1)");
|
throw new IllegalQueryOperationException("Cannot order by element " + element
|
||||||
|
+ " (the first select item is element 1)");
|
||||||
}
|
}
|
||||||
if ( element > items.size() ) {
|
if ( element > items.size() ) {
|
||||||
throw new IllegalQueryOperationException("Cannot order by element " + element + " (there are only " + items.size() + " select items)");
|
throw new IllegalQueryOperationException("Cannot order by element " + element
|
||||||
|
+ " (there are only " + items.size() + " select items)");
|
||||||
}
|
}
|
||||||
final SqmSelectableNode<?> selected = items.get( element-1 );
|
final SqmSelectableNode<?> selected = items.get( element-1 );
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,12 @@ import org.hibernate.ScrollMode;
|
||||||
import org.hibernate.ScrollableResults;
|
import org.hibernate.ScrollableResults;
|
||||||
import org.hibernate.graph.GraphSemantic;
|
import org.hibernate.graph.GraphSemantic;
|
||||||
import org.hibernate.query.BindableType;
|
import org.hibernate.query.BindableType;
|
||||||
|
import org.hibernate.query.KeyedPage;
|
||||||
import org.hibernate.query.Order;
|
import org.hibernate.query.Order;
|
||||||
import org.hibernate.query.Page;
|
import org.hibernate.query.Page;
|
||||||
import org.hibernate.query.ParameterMetadata;
|
import org.hibernate.query.ParameterMetadata;
|
||||||
import org.hibernate.query.QueryParameter;
|
import org.hibernate.query.QueryParameter;
|
||||||
|
import org.hibernate.query.SelectionQuery;
|
||||||
import org.hibernate.query.spi.QueryOptions;
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
import org.hibernate.sql.results.spi.ResultsConsumer;
|
import org.hibernate.sql.results.spi.ResultsConsumer;
|
||||||
|
@ -196,6 +198,12 @@ public abstract class DelegatingSqmSelectionQueryImplementor<R> implements SqmSe
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SelectionQuery<R> setPage(KeyedPage<R> page) {
|
||||||
|
getDelegate().setPage( page );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CacheMode getCacheMode() {
|
public CacheMode getCacheMode() {
|
||||||
return getDelegate().getCacheMode();
|
return getDelegate().getCacheMode();
|
||||||
|
|
Loading…
Reference in New Issue