DATACMNS-402 - Add support for sorting by a QueryDSL OrderSpecifier.
Previously we did only support ordering by a string or property path through Sort. In order to be able to express more type safe ordering expressions we introduce QSort as a subclass of Sort that is able to wrap QueryDSL OrderSpecifiers. To be able to separate the concerns of sorting via QueryDSL expressions better we introduce the AbstractPageRequest base class and QPageRequest as a special implementation that accepts a QSort or OrderSpecifiers for ordering. Original pull request: #59.
This commit is contained in:
committed by
Oliver Gierke
parent
9f65b57867
commit
f2ff84fb63
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.querydsl;
|
||||
|
||||
import org.springframework.data.domain.AbstractPageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import com.mysema.query.types.OrderSpecifier;
|
||||
|
||||
/**
|
||||
* Basic Java Bean implementation of {@link Pageable} with support for QueryDSL.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class QPageRequest extends AbstractPageRequest {
|
||||
|
||||
private static final long serialVersionUID = 7529171950267879273L;
|
||||
|
||||
private final QSort sort;
|
||||
|
||||
/**
|
||||
* Creates a new {@link QPageRequest}. Pages are zero indexed, thus providing 0 for {@code page} will return the first
|
||||
* page.
|
||||
*
|
||||
* @param page
|
||||
* @param size
|
||||
*/
|
||||
public QPageRequest(int page, int size) {
|
||||
this(page, size, (QSort) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link QPageRequest} with the given {@link OrderSpecifier}s applied.
|
||||
*
|
||||
* @param page
|
||||
* @param size
|
||||
* @param orderSpecifiers must not be {@literal null} or empty;
|
||||
*/
|
||||
public QPageRequest(int page, int size, OrderSpecifier<?>... orderSpecifiers) {
|
||||
this(page, size, new QSort(orderSpecifiers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link QPageRequest} with sort parameters applied.
|
||||
*
|
||||
* @param page
|
||||
* @param size
|
||||
* @param sort
|
||||
*/
|
||||
public QPageRequest(int page, int size, QSort sort) {
|
||||
super(page, size);
|
||||
|
||||
this.sort = sort;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.domain.Pageable#getSort()
|
||||
*/
|
||||
@Override
|
||||
public QSort getSort() {
|
||||
return sort;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.domain.AbstractPageRequest#next()
|
||||
*/
|
||||
@Override
|
||||
public Pageable next() {
|
||||
return new QPageRequest(getPageNumber() + 1, getPageSize(), getSort());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.domain.AbstractPageRequest#previous()
|
||||
*/
|
||||
@Override
|
||||
public Pageable previous() {
|
||||
return new QPageRequest(getPageNumber() - 1, getPageSize(), getSort());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.domain.AbstractPageRequest#first()
|
||||
*/
|
||||
@Override
|
||||
public Pageable first() {
|
||||
return new QPageRequest(0, getPageSize(), getSort());
|
||||
}
|
||||
}
|
||||
153
src/main/java/org/springframework/data/querydsl/QSort.java
Normal file
153
src/main/java/org/springframework/data/querydsl/QSort.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.querydsl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.OrderSpecifier;
|
||||
|
||||
/**
|
||||
* Sort option for queries that wraps a querydsl {@link OrderSpecifier}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class QSort extends Sort implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6701117396842171930L;
|
||||
|
||||
private final List<OrderSpecifier<?>> orderSpecifiers;
|
||||
|
||||
/**
|
||||
* Creates a new {@link QSort} instance with the given {@link OrderSpecifier}s.
|
||||
*
|
||||
* @param orderSpecifiers must not be {@literal null} or empty;
|
||||
*/
|
||||
public QSort(OrderSpecifier<?>... orderSpecifiers) {
|
||||
this(Arrays.asList(orderSpecifiers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link QSort} instance with the given {@link OrderSpecifier}s.
|
||||
*
|
||||
* @param orderSpecifiers must not be {@literal null} or empty;
|
||||
*/
|
||||
public QSort(List<OrderSpecifier<?>> orderSpecifiers) {
|
||||
super(toOrders(orderSpecifiers));
|
||||
Assert.notEmpty(orderSpecifiers, "Order specifiers must not be null or empty!");
|
||||
this.orderSpecifiers = orderSpecifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link OrderSpecifier}s into a list of {@link Order}s.
|
||||
*
|
||||
* @param orderSpecifiers must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
private static List<Order> toOrders(List<OrderSpecifier<?>> orderSpecifiers) {
|
||||
|
||||
Assert.notEmpty(orderSpecifiers, "Order specifiers must not be null or empty!");
|
||||
|
||||
List<Order> orders = new ArrayList<Sort.Order>();
|
||||
for (OrderSpecifier<?> orderSpecifier : orderSpecifiers) {
|
||||
orders.add(toOrder(orderSpecifier));
|
||||
}
|
||||
|
||||
return orders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link OrderSpecifier} into an {@link Order}.
|
||||
*
|
||||
* @param orderSpecifier must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static Order toOrder(OrderSpecifier<?> orderSpecifier) {
|
||||
|
||||
Assert.notNull(orderSpecifier, "Order specifier must not be null!");
|
||||
|
||||
Expression<?> target = orderSpecifier.getTarget();
|
||||
Object targetElement = ((com.mysema.query.types.Path) target).getMetadata().getElement();
|
||||
|
||||
Assert.notNull(targetElement, "Target element must not be null!");
|
||||
|
||||
return new Order(targetElement.toString()).with(orderSpecifier.isAscending() ? Direction.ASC : Direction.DESC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the orderSpecifier
|
||||
*/
|
||||
public List<OrderSpecifier<?>> getOrderSpecifiers() {
|
||||
return orderSpecifiers;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.domain.Sort#and(org.springframework.data.domain.Sort)
|
||||
*/
|
||||
@Override
|
||||
public Sort and(Sort sort) {
|
||||
throw new UnsupportedOperationException("You cannot combine a querydsl based QSort with an arbitrary Sort!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link QSort} consisting of the {@link OrderSpecifier}s of the current {@code QSort} combined with
|
||||
* the ones from the given {@code QSort}.
|
||||
*
|
||||
* @param sort can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public QSort and(QSort sort) {
|
||||
return sort == null ? this : and(sort.getOrderSpecifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link QSort} consisting of the {@link OrderSpecifier}s of the current {@link QSort} combined with
|
||||
* the given ones.
|
||||
*
|
||||
* @param orderSpecifiers must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
public QSort and(List<OrderSpecifier<?>> orderSpecifiers) {
|
||||
|
||||
Assert.notEmpty(orderSpecifiers, "OrderSpecifiers must not be null or empty!");
|
||||
|
||||
List<OrderSpecifier<?>> newOrderSpecifiers = new ArrayList<OrderSpecifier<?>>(this.orderSpecifiers);
|
||||
newOrderSpecifiers.addAll(orderSpecifiers);
|
||||
|
||||
return new QSort(newOrderSpecifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link QSort} consisting of the {@link OrderSpecifier}s of the current {@link QSort} combined with
|
||||
* the given ones.
|
||||
*
|
||||
* @param orderSpecifiers must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
public QSort and(OrderSpecifier<?>... orderSpecifiers) {
|
||||
|
||||
Assert.notEmpty(orderSpecifiers, "OrderSpecifiers must not be null or empty!");
|
||||
|
||||
return and(Arrays.asList(orderSpecifiers));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user