mirror of
https://github.com/querydsl/querydsl.git
synced 2026-07-06 21:05:50 +08:00
Merge pull request #2108 from harshtuna/collections-order-nulls-last
fix for #2106 enable NullsLast support in querydsl-collections orderBy()
This commit is contained in:
commit
3411f7857d
@ -13,6 +13,7 @@ A huge thanks goes out to all contributors that made this release possible in th
|
||||
* **[@mp911de](https://github.com/mp911de)**, for working on the MongoDB Document API;
|
||||
* **[@daniel-shuy](https://github.com/daniel-shuy)**, for working on decoupling `querydsl-sql` from `joda-time:joda-time`;
|
||||
* **[@heesuk-ahn](https://github.com/heesuk-ahn)**, for working on improved Hibernate support and count query generation in `JPASQLQuery`;
|
||||
* **[@harshtuna](https://github.com/harshtuna)**, for working on NullsLast ordering in `querydsl-collections`;
|
||||
* **[@jwgmeligmeyling](https://github.com/jwgmeligmeyling)**, **[@Shredder121](https://github.com/Shredder121)**, **[@johnktims](https://github.com/johnktims)**, **[@idosal](https://github.com/idosal)** and **[@robertandrewbain](https://github.com/robertandrewbain)**.
|
||||
|
||||
#### New features
|
||||
@ -34,6 +35,7 @@ A huge thanks goes out to all contributors that made this release possible in th
|
||||
does not have to be available at runtime and is not a transitive dependency.
|
||||
* [#658](https://github.com/querydsl/querydsl/issues/658) - Added `JPAExpressions#treat` which can be used to generate JPA 2.1 Treated path expressions.
|
||||
* [#2666](https://github.com/querydsl/querydsl/issues/2666) - More descriptive error message when using unsupported query features in JPA.
|
||||
* [#2106](https://github.com/querydsl/querydsl/issues/2106) - Support NullsLast ordering in `querydsl-collections`.
|
||||
|
||||
#### Bugfixes
|
||||
|
||||
|
||||
@ -214,13 +214,15 @@ public class DefaultQueryEngine implements QueryEngine {
|
||||
List<OrderSpecifier<?>> orderBy = metadata.getOrderBy();
|
||||
Expression<Object>[] orderByExpr = new Expression[orderBy.size()];
|
||||
boolean[] directions = new boolean[orderBy.size()];
|
||||
boolean[] nullsLast = new boolean[orderBy.size()];
|
||||
for (int i = 0; i < orderBy.size(); i++) {
|
||||
orderByExpr[i] = (Expression) orderBy.get(i).getTarget();
|
||||
directions[i] = orderBy.get(i).getOrder() == Order.ASC;
|
||||
nullsLast[i] = orderBy.get(i).getNullHandling() == OrderSpecifier.NullHandling.NullsLast;
|
||||
}
|
||||
Expression<?> expr = new ArrayConstructorExpression<Object>(Object[].class, orderByExpr);
|
||||
Evaluator orderEvaluator = evaluatorFactory.create(metadata, sources, expr);
|
||||
list.sort(new MultiComparator(orderEvaluator, directions));
|
||||
list.sort(new MultiComparator(orderEvaluator, directions, nullsLast));
|
||||
}
|
||||
|
||||
private List<?> project(QueryMetadata metadata, List<Expression<?>> sources, List<?> list) {
|
||||
|
||||
@ -23,7 +23,6 @@ import com.querydsl.core.util.NullSafeComparableComparator;
|
||||
* {@code MultiComparator} compares arrays
|
||||
*
|
||||
* @param <T> element type
|
||||
*
|
||||
* @author tiwe
|
||||
*/
|
||||
public class MultiComparator<T> implements Comparator<T>, Serializable {
|
||||
@ -35,16 +34,19 @@ public class MultiComparator<T> implements Comparator<T>, Serializable {
|
||||
|
||||
private final boolean[] asc;
|
||||
|
||||
private final boolean[] nullsLast;
|
||||
|
||||
private final transient Evaluator<Object[]> ev;
|
||||
|
||||
public MultiComparator(Evaluator<Object[]> ev, boolean[] directions) {
|
||||
public MultiComparator(Evaluator<Object[]> ev, boolean[] directions, boolean[] nullsLast) {
|
||||
this.ev = ev;
|
||||
this.asc = directions.clone();
|
||||
this.nullsLast = nullsLast.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(T o1, T o2) {
|
||||
if (o1.getClass().isArray()) {
|
||||
if (o1 instanceof Object[]) {
|
||||
return innerCompare(ev.evaluate((Object[]) o1), ev.evaluate((Object[]) o2));
|
||||
} else {
|
||||
return innerCompare(ev.evaluate(o1), ev.evaluate(o2));
|
||||
@ -53,16 +55,16 @@ public class MultiComparator<T> implements Comparator<T>, Serializable {
|
||||
|
||||
private int innerCompare(Object[] o1, Object[] o2) {
|
||||
for (int i = 0; i < o1.length; i++) {
|
||||
int res;
|
||||
if (o1[i] == null) {
|
||||
res = o2[i] == null ? 0 : -1;
|
||||
return o2[i] == null ? 0 : nullsLast[i] ? 1 : -1;
|
||||
} else if (o2[i] == null) {
|
||||
res = 1;
|
||||
return nullsLast[i] ? -1 : 1;
|
||||
} else {
|
||||
int res;
|
||||
res = naturalOrder.compare(o1[i], o2[i]);
|
||||
}
|
||||
if (res != 0) {
|
||||
return asc[i] ? res : -res;
|
||||
if (res != 0) {
|
||||
return asc[i] ? res : -res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@ -34,7 +34,8 @@ public class MultiComparatorTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
MultiComparator<Object[]> comparator = new MultiComparator<Object[]>(evaluator, new boolean[]{true, true});
|
||||
MultiComparator<Object[]> comparator = new MultiComparator<Object[]>(evaluator, new boolean[]{true, true},
|
||||
new boolean[]{true, true});
|
||||
assertTrue(comparator.compare(new Object[]{"a", "b"}, new Object[]{"a","c"}) < 0);
|
||||
assertTrue(comparator.compare(new Object[]{"b", "a"}, new Object[]{"a","b"}) > 0);
|
||||
assertTrue(comparator.compare(new Object[]{"b", "b"}, new Object[]{"b","b"}) == 0);
|
||||
|
||||
@ -60,9 +60,25 @@ public class OrderTest extends AbstractQueryTest {
|
||||
|
||||
@Test
|
||||
public void with_null() {
|
||||
List<Cat> cats = Arrays.asList(new Cat(), new Cat("Bob"));
|
||||
assertEquals(cats, query().from(cat, cats).orderBy(cat.name.asc()).select(cat).fetch());
|
||||
assertEquals(Arrays.asList(cats.get(1), cats.get(0)), query().from(cat, cats).orderBy(cat.name.desc()).select(cat).fetch());
|
||||
Cat unknown = new Cat();
|
||||
Cat bob = new Cat("Bob");
|
||||
Cat alex = new Cat("Alex");
|
||||
List<Cat> cats = Arrays.asList(alex, unknown, bob);
|
||||
assertEquals(Arrays.asList(unknown, alex, bob),
|
||||
query().from(cat, cats).orderBy(cat.name.asc()).select(cat).fetch());
|
||||
assertEquals(Arrays.asList(unknown, bob, alex),
|
||||
query().from(cat, cats).orderBy(cat.name.desc()).select(cat).fetch());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void with_nulls_last() {
|
||||
Cat unknown = new Cat();
|
||||
Cat bob = new Cat("Bob");
|
||||
Cat alex = new Cat("Alex");
|
||||
List<Cat> cats = Arrays.asList(alex, unknown, bob);
|
||||
assertEquals(Arrays.asList(bob, alex, unknown),
|
||||
query().from(this.cat, cats).orderBy(this.cat.name.desc().nullsLast()).select(this.cat).fetch());
|
||||
assertEquals(Arrays.asList(alex, bob, unknown),
|
||||
query().from(this.cat, cats).orderBy(this.cat.name.asc().nullsLast()).select(this.cat).fetch());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user