mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-29 00:08:50 +00:00
auomatically append "order by id" when paging and query.orderById = true (#1275)
Add ServerConfig.setDefaultOrderById() and query.orderById(boolean) ... to control automatically append "order by id" with paging query
This commit is contained in:
committed by
Rob Bygrave
parent
0cba0664f8
commit
a712be2917
@@ -1,7 +1,6 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.OrderBy;
|
||||
import io.ebean.PersistenceContextScope;
|
||||
@@ -338,7 +337,7 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
/**
|
||||
* Return a copy of the query attaching to a different EbeanServer.
|
||||
*/
|
||||
SpiQuery<T> copy(EbeanServer server);
|
||||
SpiQuery<T> copy(SpiEbeanServer server);
|
||||
|
||||
/**
|
||||
* Return the type of query (List, Set, Map, Bean, rowCount etc).
|
||||
@@ -593,6 +592,11 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
*/
|
||||
boolean checkPagingOrderBy();
|
||||
|
||||
/**
|
||||
* Return true if there is no Order By clause.
|
||||
*/
|
||||
boolean orderByIsEmpty();
|
||||
|
||||
/**
|
||||
* Return the Order By clause or null if there is none defined.
|
||||
*/
|
||||
|
||||
@@ -3053,13 +3053,8 @@ public class BeanDescriptor<T> implements BeanType<T> {
|
||||
*/
|
||||
public void appendOrderById(SpiQuery<T> query) {
|
||||
|
||||
if (idProperty != null && !idProperty.isEmbedded()) {
|
||||
SpiRawSql rawSql = query.getRawSql();
|
||||
if (rawSql != null) {
|
||||
query.order(rawSql.getSql().getOrderBy());
|
||||
} else {
|
||||
query.order().asc(idProperty.getName());
|
||||
}
|
||||
if (idProperty != null && !idProperty.isEmbedded() && !query.order().containsProperty(idProperty.getName())) {
|
||||
query.order().asc(idProperty.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -190,7 +190,6 @@ public class CQueryEngine {
|
||||
*/
|
||||
public <T> QueryIterator<T> findIterate(OrmQueryRequest<T> request) {
|
||||
|
||||
prepareForPaging(request);
|
||||
CQuery<T> cquery = queryBuilder.buildQuery(request);
|
||||
request.setCancelableQuery(cquery);
|
||||
|
||||
@@ -326,24 +325,12 @@ public class CQueryEngine {
|
||||
return historySupport.getSysPeriodLower(rootTableAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
* deemed to be a be a paging query - check that the order by contains the id
|
||||
* property to ensure unique row ordering for predicable paging but only in
|
||||
* case, this is not a distinct query
|
||||
*/
|
||||
private <T> void prepareForPaging(OrmQueryRequest<T> request) {
|
||||
SpiQuery<T> query = request.getQuery();
|
||||
if (query.checkPagingOrderBy()) {
|
||||
request.getBeanDescriptor().appendOrderById(query);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a list/map/set of beans.
|
||||
*/
|
||||
<T> BeanCollection<T> findMany(OrmQueryRequest<T> request) {
|
||||
|
||||
prepareForPaging(request);
|
||||
|
||||
CQuery<T> cquery = queryBuilder.buildQuery(request);
|
||||
request.setCancelableQuery(cquery);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package io.ebeaninternal.server.querydefn;
|
||||
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Expression;
|
||||
import io.ebean.ExpressionFactory;
|
||||
import io.ebean.ExpressionList;
|
||||
@@ -32,6 +31,7 @@ import io.ebeaninternal.api.CQueryPlanKey;
|
||||
import io.ebeaninternal.api.HashQuery;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionList;
|
||||
import io.ebeaninternal.api.SpiExpressionValidation;
|
||||
@@ -39,6 +39,7 @@ import io.ebeaninternal.api.SpiNamedParam;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.api.SpiQuerySecondary;
|
||||
import io.ebeaninternal.server.autotune.ProfilingListener;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.TableJoin;
|
||||
@@ -75,7 +76,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private final BeanDescriptor<T> beanDescriptor;
|
||||
|
||||
private final EbeanServer server;
|
||||
private final SpiEbeanServer server;
|
||||
|
||||
private final ExpressionFactory expressionFactory;
|
||||
|
||||
@@ -254,6 +255,8 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private String nativeSql;
|
||||
|
||||
private boolean orderById;
|
||||
|
||||
/**
|
||||
* Identity the query for profiling purposes (expected to be unique for a bean type).
|
||||
*/
|
||||
@@ -261,10 +264,11 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private ProfileLocation profileLocation;
|
||||
|
||||
public DefaultOrmQuery(BeanDescriptor<T> desc, EbeanServer server, ExpressionFactory expressionFactory) {
|
||||
public DefaultOrmQuery(BeanDescriptor<T> desc, SpiEbeanServer server, ExpressionFactory expressionFactory) {
|
||||
this.beanDescriptor = desc;
|
||||
this.beanType = desc.getBeanType();
|
||||
this.server = server;
|
||||
this.orderById = server.getServerConfig().isDefaultOrderById();
|
||||
this.expressionFactory = expressionFactory;
|
||||
this.detail = new OrmQueryDetail();
|
||||
}
|
||||
@@ -279,6 +283,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isFindAll() {
|
||||
return whereExpressions == null && nativeSql == null && rawSql == null;
|
||||
}
|
||||
@@ -304,6 +309,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getProfileId() {
|
||||
return profileId;
|
||||
}
|
||||
@@ -717,8 +723,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultOrmQuery<T> copy(EbeanServer server) {
|
||||
|
||||
public DefaultOrmQuery<T> copy(SpiEbeanServer server) {
|
||||
DefaultOrmQuery<T> copy = new DefaultOrmQuery<>(beanDescriptor, server, expressionFactory);
|
||||
copy.m2mIncludeJoin = m2mIncludeJoin;
|
||||
copy.profilingListener = profilingListener;
|
||||
@@ -742,6 +747,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
if (orderBy != null) {
|
||||
copy.orderBy = orderBy.copy();
|
||||
}
|
||||
copy.orderById = orderById;
|
||||
if (bindParams != null) {
|
||||
copy.bindParams = bindParams.copy();
|
||||
}
|
||||
@@ -1037,6 +1043,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
public CQueryPlanKey prepare(BeanQueryRequest<?> request) {
|
||||
|
||||
prepareExpressions(request);
|
||||
prepareForPaging((OrmQueryRequest) request);
|
||||
queryPlanKey = createQueryPlanKey();
|
||||
return queryPlanKey;
|
||||
}
|
||||
@@ -1054,6 +1061,24 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* deemed to be a be a paging query - check that the order by contains the id
|
||||
* property to ensure unique row ordering for predicable paging but only in
|
||||
* case, this is not a distinct query
|
||||
*/
|
||||
private void prepareForPaging(OrmQueryRequest<T> request) {
|
||||
|
||||
// add the rawSql statement - if any
|
||||
if (orderByIsEmpty()) {
|
||||
SpiRawSql rawSql = getRawSql();
|
||||
if (rawSql != null && rawSql.getSql() != null) {
|
||||
order(rawSql.getSql().getOrderBy());
|
||||
}
|
||||
}
|
||||
if (checkPagingOrderBy()) {
|
||||
request.getBeanDescriptor().appendOrderById(this);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Calculate a hash based on the bind values used in the query.
|
||||
* <p>
|
||||
@@ -1388,10 +1413,11 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
@Override
|
||||
public boolean checkPagingOrderBy() {
|
||||
return (maxRows > 1 || firstRow > 0) && !distinct && orderByIsEmpty();
|
||||
return (maxRows > 1 || firstRow > 0) && !distinct && (orderByIsEmpty() || isOrderById());
|
||||
}
|
||||
|
||||
private boolean orderByIsEmpty() {
|
||||
@Override
|
||||
public boolean orderByIsEmpty() {
|
||||
return orderBy == null || orderBy.isEmpty();
|
||||
}
|
||||
|
||||
@@ -1776,4 +1802,14 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
public ProfileLocation getProfileLocation() {
|
||||
return profileLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> orderById(boolean orderById) {
|
||||
this.orderById = orderById;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isOrderById() {
|
||||
return orderById;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user