From bf304095c33e4b9beb95585b00565f514370be18 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Fri, 27 May 2016 16:43:00 +0200 Subject: [PATCH] DATAJPA-905 - Count queries for Specifications don't use orders anymore. Count queries that are executed in the context of paginated queries using Specifications now get their order specifications removed as they get rejected by some databases. --- .../support/SimpleJpaRepository.java | 16 ++++--------- .../jpa/domain/sample/UserSpecifications.java | 24 +++++++++++++++++-- .../jpa/repository/UserRepositoryTests.java | 15 ++++++++++++ 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java index 379b78134..a64d34243 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java @@ -33,6 +33,7 @@ import javax.persistence.Query; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Order; import javax.persistence.criteria.ParameterExpression; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; @@ -678,21 +679,12 @@ public class SimpleJpaRepository query.select(builder.count(root)); } + // Remove all Orders the Specifications might have applied + query.orderBy(Collections. emptyList()); + return em.createQuery(query); } - /** - * Applies the given {@link Specification} to the given {@link CriteriaQuery}. - * - * @param spec can be {@literal null}. - * @param query must not be {@literal null}. - * @return - */ - private Root applySpecificationToCriteria(Specification spec, CriteriaQuery query) { - return applySpecificationToCriteria(spec, getDomainClass(), query); - - } - /** * Applies the given {@link Specification} to the given {@link CriteriaQuery}. * diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/UserSpecifications.java b/src/test/java/org/springframework/data/jpa/domain/sample/UserSpecifications.java index 8308d08e7..7af93d8c2 100644 --- a/src/test/java/org/springframework/data/jpa/domain/sample/UserSpecifications.java +++ b/src/test/java/org/springframework/data/jpa/domain/sample/UserSpecifications.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 the original author or authors. + * Copyright 2008-2016 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. @@ -68,6 +68,26 @@ public class UserSpecifications { }; } + /** + * A {@link Specification} to do a like-match on a {@link User}'s lastname but also adding a sort order on the + * firstname. + * + * @param firstname + * @return + */ + public static Specification userHasLastnameLikeWithSort(final String expression) { + + return new Specification() { + + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + + query.orderBy(cb.asc(root.get("firstname"))); + + return cb.like(root.get("lastname").as(String.class), String.format("%%%s%%", expression)); + } + }; + } + private static Specification simplePropertySpec(final String property, final Object value) { return new Specification() { @@ -78,4 +98,4 @@ public class UserSpecifications { } }; } -} \ No newline at end of file +} diff --git a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java index 6d0563fc6..44a3d5798 100644 --- a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java @@ -2382,6 +2382,21 @@ public class UserRepositoryTests { assertThat(exists, is(true)); } + /** + * @see DATAJPA-905 + */ + @Test + public void excutesPagedSpecificationSettingAnOrder() { + + flushTestUsers(); + + Page result = repository.findAll(where(userHasLastnameLikeWithSort("e")), new PageRequest(0, 1)); + + assertThat(result.getTotalElements(), is(2L)); + assertThat(result.getNumberOfElements(), is(1)); + assertThat(result.getContent().get(0), is(thirdUser)); + } + private Page executeSpecWithSort(Sort sort) { flushTestUsers();