HHH-17779 support for key-based pagination
change the API slightly
This commit is contained in:
parent
b9e01fec4f
commit
dbd15fd690
|
@ -45,6 +45,7 @@ import org.hibernate.procedure.spi.ParameterStrategy;
|
|||
import org.hibernate.procedure.spi.ProcedureCallImplementor;
|
||||
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
|
||||
import org.hibernate.query.BindableType;
|
||||
import org.hibernate.query.KeyedPage;
|
||||
import org.hibernate.query.KeyedResultList;
|
||||
import org.hibernate.query.Order;
|
||||
import org.hibernate.query.OutputableType;
|
||||
|
@ -971,7 +972,7 @@ public class ProcedureCallImpl<R>
|
|||
}
|
||||
|
||||
@Override
|
||||
public KeyedResultList<R> getKeyedResultList() {
|
||||
public KeyedResultList<R> getKeyedResultList(KeyedPage<R> page) {
|
||||
throw new UnsupportedOperationException("getKeyedResultList() not implemented for ProcedureCall/StoredProcedureQuery");
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.query;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
|
@ -13,11 +15,35 @@ 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}.
|
||||
* <p>
|
||||
* A specification for an initial page may be obtained from
|
||||
* an instance of {@link Page}.
|
||||
* <pre>
|
||||
* KeyedPage<Book> firstPage = Page.first(10).keyedBy(asc(Book_.isbn)));
|
||||
* </pre>
|
||||
* A {@link KeyedResultList} then may be obtained by calling
|
||||
* {@link SelectionQuery#getKeyedResultList(KeyedPage)}.
|
||||
* <pre>
|
||||
* KeyedResultList results =
|
||||
* session.createQuery("from Book", Book.class)
|
||||
* .getKeyedResultList(firstPage);
|
||||
* </pre>
|
||||
* The following page may be obtained from {@link KeyedResultList#getNextPage()}.
|
||||
* <pre>
|
||||
* KeyedPage<Book> nextPage = results.getNextPage();
|
||||
* KeyedResultList moreResults =
|
||||
* session.createQuery("from Book", Book.class)
|
||||
* .getKeyedResultList(nextPage);
|
||||
* </pre>
|
||||
*
|
||||
* @since 6.5
|
||||
*
|
||||
* @see SelectionQuery#getKeyedResultList(KeyedPage)
|
||||
* @see KeyedResultList
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
@Incubating
|
||||
public class KeyedPage<R> {
|
||||
private final List<Order<? super R>> keyDefinition;
|
||||
private final Page page;
|
||||
|
@ -27,7 +53,7 @@ public class KeyedPage<R> {
|
|||
this( keyDefinition, page, null );
|
||||
}
|
||||
|
||||
public KeyedPage(List<Order<? super R>> keyDefinition, Page page, List<Comparable<?>> key) {
|
||||
KeyedPage(List<Order<? super R>> keyDefinition, Page page, List<Comparable<?>> key) {
|
||||
this.page = page;
|
||||
this.keyDefinition = unmodifiableList(keyDefinition);
|
||||
this.key = key;
|
||||
|
@ -48,4 +74,8 @@ public class KeyedPage<R> {
|
|||
public List<Comparable<?>> getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public static <R> KeyedPage<R> forKey(List<Order<? super R>> keyDefinition, Page page, List<Comparable<?>> key) {
|
||||
return new KeyedPage<>( keyDefinition, page, key );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,25 @@
|
|||
*/
|
||||
package org.hibernate.query;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Support for pagination based on a unique key of the result
|
||||
* set instead of the {@link Page#getFirstResult() offset}.
|
||||
* An instance of this class represent a page of results returned
|
||||
* by {@link SelectionQuery#getKeyedResultList(KeyedPage)}. The
|
||||
* actual query results are held in {@link #getResultList()}.
|
||||
*
|
||||
* @since 6.5
|
||||
*
|
||||
* @see KeyedPage
|
||||
* @see SelectionQuery#getKeyedResultList(KeyedPage)
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
@Incubating
|
||||
public class KeyedResultList<R> {
|
||||
private final List<R> resultList;
|
||||
private final KeyedPage<R> page;
|
||||
|
|
|
@ -86,6 +86,9 @@ public class Page {
|
|||
return first( size );
|
||||
}
|
||||
|
||||
public <R> KeyedPage<R> keyedBy(Order<? super R> keyDefinition) {
|
||||
return new KeyedPage<>( List.of(keyDefinition), this );
|
||||
}
|
||||
public <R> KeyedPage<R> keyedBy(List<Order<? super R>> keyDefinition) {
|
||||
return new KeyedPage<>( keyDefinition, this );
|
||||
}
|
||||
|
|
|
@ -903,11 +903,6 @@ public interface Query<R> extends SelectionQuery<R>, MutationQuery, TypedQuery<R
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
default SelectionQuery<R> setPage(KeyedPage<R> page) {
|
||||
throw new UnsupportedOperationException("keyed paging not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
Query<R> setHint(String hintName, Object value);
|
||||
|
||||
|
|
|
@ -220,8 +220,23 @@ public interface SelectionQuery<R> extends CommonQueryContract {
|
|||
@Incubating
|
||||
long getResultCount();
|
||||
|
||||
/**
|
||||
* Execute the query and return the results for the given
|
||||
* {@linkplain KeyedPage page}, using key-based pagination.
|
||||
*
|
||||
* @param page the key-based specification of the page as
|
||||
* an instance of {@link KeyedPage}
|
||||
*
|
||||
* @return the query results and the key of the next page
|
||||
* as an instance of {@link KeyedResultList}
|
||||
*
|
||||
* @since 6.5
|
||||
*
|
||||
* @see KeyedPage
|
||||
* @see KeyedResultList
|
||||
*/
|
||||
@Incubating
|
||||
KeyedResultList<R> getKeyedResultList();
|
||||
KeyedResultList<R> getKeyedResultList(KeyedPage<R> page);
|
||||
|
||||
SelectionQuery<R> setHint(String hintName, Object value);
|
||||
|
||||
|
@ -398,16 +413,6 @@ public interface SelectionQuery<R> extends CommonQueryContract {
|
|||
@Incubating
|
||||
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,
|
||||
* the query inherits the {@link CacheMode} of the session from which
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.hibernate.jpa.spi.NativeQueryTupleTransformer;
|
|||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.BindableType;
|
||||
import org.hibernate.query.KeyedPage;
|
||||
import org.hibernate.query.KeyedResultList;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.Order;
|
||||
|
@ -639,7 +640,7 @@ public class NativeQueryImpl<R>
|
|||
}
|
||||
|
||||
@Override
|
||||
public KeyedResultList<R> getKeyedResultList() {
|
||||
public KeyedResultList<R> getKeyedResultList(KeyedPage<R> page) {
|
||||
throw new UnsupportedOperationException("native queries do not support key-based pagination");
|
||||
}
|
||||
|
||||
|
|
|
@ -52,8 +52,6 @@ import static org.hibernate.query.sqm.tree.SqmCopyContext.noParamCopyContext;
|
|||
*/
|
||||
abstract class AbstractSqmSelectionQuery<R> extends AbstractSelectionQuery<R> {
|
||||
|
||||
private KeyedPage<R> keyedPage;
|
||||
|
||||
AbstractSqmSelectionQuery(SharedSessionContractImplementor session) {
|
||||
super(session);
|
||||
}
|
||||
|
@ -147,12 +145,6 @@ abstract class AbstractSqmSelectionQuery<R> extends AbstractSelectionQuery<R> {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectionQuery<R> setPage(KeyedPage<R> page) {
|
||||
keyedPage = page;
|
||||
return this;
|
||||
}
|
||||
|
||||
static class KeyedResult<R> {
|
||||
final R result;
|
||||
final List<Comparable<?>> key;
|
||||
|
@ -220,16 +212,16 @@ abstract class AbstractSqmSelectionQuery<R> extends AbstractSelectionQuery<R> {
|
|||
// setParameter( parameter, keyValue );
|
||||
switch ( key.getDirection() ) {
|
||||
case ASCENDING:
|
||||
return builder.greaterThan( path, builder.literal(keyValue) );
|
||||
return builder.greaterThan( path, keyValue );
|
||||
case DESCENDING:
|
||||
return builder.lessThan( path, builder.literal(keyValue) );
|
||||
return builder.lessThan( path, keyValue );
|
||||
default:
|
||||
throw new AssertionFailure("Unrecognized key direction");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyedResultList<R> getKeyedResultList() {
|
||||
public KeyedResultList<R> getKeyedResultList(KeyedPage<R> keyedPage) {
|
||||
if ( keyedPage == null ) {
|
||||
throw new IllegalStateException( "KeyedPage was not set" );
|
||||
}
|
||||
|
@ -254,7 +246,7 @@ abstract class AbstractSqmSelectionQuery<R> extends AbstractSelectionQuery<R> {
|
|||
final List<Comparable<?>> keyOfLastResult =
|
||||
executed.isEmpty() ? key : executed.get( executed.size()-1 ).getKey();
|
||||
return new KeyedResultList<>( executed.stream().map(KeyedResult::getResult).collect(toList()),
|
||||
keyedPage, new KeyedPage<>(keyDefinition, page.next(), keyOfLastResult) );
|
||||
keyedPage, KeyedPage.forKey( keyDefinition, page.next(), keyOfLastResult ) );
|
||||
}
|
||||
|
||||
public abstract Class<R> getExpectedResultType();
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
import org.hibernate.query.BindableType;
|
||||
import org.hibernate.query.IllegalQueryOperationException;
|
||||
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
|
||||
import org.hibernate.query.KeyedPage;
|
||||
import org.hibernate.query.Order;
|
||||
import org.hibernate.query.Page;
|
||||
import org.hibernate.query.Query;
|
||||
|
@ -923,11 +922,6 @@ public class QuerySqmImpl<R>
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<R> setPage(KeyedPage<R> page) {
|
||||
super.setPage(page);
|
||||
return this;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// hints
|
||||
|
|
|
@ -25,12 +25,10 @@ import org.hibernate.ScrollMode;
|
|||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.graph.GraphSemantic;
|
||||
import org.hibernate.query.BindableType;
|
||||
import org.hibernate.query.KeyedPage;
|
||||
import org.hibernate.query.Order;
|
||||
import org.hibernate.query.Page;
|
||||
import org.hibernate.query.ParameterMetadata;
|
||||
import org.hibernate.query.QueryParameter;
|
||||
import org.hibernate.query.SelectionQuery;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.sql.results.spi.ResultsConsumer;
|
||||
|
@ -198,12 +196,6 @@ public abstract class DelegatingSqmSelectionQueryImplementor<R> implements SqmSe
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectionQuery<R> setPage(KeyedPage<R> page) {
|
||||
getDelegate().setPage( page );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheMode getCacheMode() {
|
||||
return getDelegate().getCacheMode();
|
||||
|
|
Loading…
Reference in New Issue