DATAJPA-551 - Add support for limiting the query result in the query derivation mechanism.

We now support to restrict the results of a query method via the "Top" or "First" keyword within the method name. We adjust the firstResult offset of the query in case we detect a tighter bound on the result size limit form the derived query method that is smaller than the page size of the given Pageable.

Added test cases for Paged and Sliced query executions.

Original pull request: #96.
This commit is contained in:
Thomas Darimont
2014-06-05 14:41:47 +02:00
committed by Oliver Gierke
parent 09d32cb3f5
commit 43d035fe54
3 changed files with 231 additions and 1 deletions

View File

@@ -128,7 +128,37 @@ public class PartTreeJpaQuery extends AbstractJpaQuery {
}
TypedQuery<?> jpaQuery = createQuery(criteriaQuery);
return invokeBinding(getBinder(values, expressions), jpaQuery);
return restrictMaxResultsIfNecessary(invokeBinding(getBinder(values, expressions), jpaQuery));
}
/**
* Restricts the max results of the given {@link Query} if the current {@code tree} marks this {@code query} as
* limited.
*
* @param query
* @return
*/
private Query restrictMaxResultsIfNecessary(Query query) {
if (tree.isLimiting()) {
if (query.getMaxResults() != Integer.MAX_VALUE) {
/*
* In order to return the correct results, we have to adjust the first result offset to be returned if:
* - a Pageable parameter is present
* - AND the requested page number > 0
* - AND the requested page size was bigger than the derived result limitation via the First/Top keyword.
*/
if (query.getMaxResults() > tree.getMaxResults() && query.getFirstResult() > 0) {
query.setFirstResult(query.getFirstResult() - (query.getMaxResults() - tree.getMaxResults()));
}
}
query.setMaxResults(tree.getMaxResults());
}
return query;
}
/**

View File

@@ -49,6 +49,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
@@ -1421,6 +1422,140 @@ public class UserRepositoryTests {
assertThat(result.getContent().size(), is(1));
}
/**
* @see DATAJPA-551
*/
@Test
public void findOldestUser() {
flushTestUsers();
User oldest = thirdUser;
assertThat(repository.findFirstByOrderByAgeDesc(), is(oldest));
assertThat(repository.findFirst1ByOrderByAgeDesc(), is(oldest));
}
/**
* @see DATAJPA-551
*/
@Test
public void findYoungestUser() {
flushTestUsers();
User youngest = firstUser;
assertThat(repository.findTopByOrderByAgeAsc(), is(youngest));
assertThat(repository.findTop1ByOrderByAgeAsc(), is(youngest));
}
/**
* @see DATAJPA-551
*/
@Test
public void find2OldestUsers() {
flushTestUsers();
User oldest1 = thirdUser;
User oldest2 = secondUser;
assertThat(repository.findFirst2ByOrderByAgeDesc(), hasItems(oldest1, oldest2));
assertThat(repository.findTop2ByOrderByAgeDesc(), hasItems(oldest1, oldest2));
}
/**
* @see DATAJPA-551
*/
@Test
public void find2YoungestUsers() {
flushTestUsers();
User youngest1 = firstUser;
User youngest2 = fourthUser;
assertThat(repository.findFirst2UsersBy(new Sort(ASC, "age")), hasItems(youngest1, youngest2));
assertThat(repository.findTop2UsersBy(new Sort(ASC, "age")), hasItems(youngest1, youngest2));
}
/**
* @see DATAJPA-551
*/
@Test
public void find3YoungestUsersPageableWithPageSize2() {
flushTestUsers();
User youngest1 = firstUser;
User youngest2 = fourthUser;
User youngest3 = secondUser;
Page<User> firstPage = repository.findFirst3UsersBy(new PageRequest(0, 2, ASC, "age"));
assertThat(firstPage.getContent(), hasItems(youngest1, youngest2));
Page<User> secondPage = repository.findFirst3UsersBy(new PageRequest(1, 2, ASC, "age"));
assertThat(secondPage.getContent(), hasItems(youngest3));
}
/**
* @see DATAJPA-551
*/
@Test
public void find2YoungestUsersPageableWithPageSize3() {
flushTestUsers();
User youngest1 = firstUser;
User youngest2 = fourthUser;
User youngest3 = secondUser;
Page<User> firstPage = repository.findFirst2UsersBy(new PageRequest(0, 3, ASC, "age"));
assertThat(firstPage.getContent(), hasItems(youngest1, youngest2));
Page<User> secondPage = repository.findFirst2UsersBy(new PageRequest(1, 3, ASC, "age"));
assertThat(secondPage.getContent(), hasItems(youngest3));
}
/**
* @see DATAJPA-551
*/
@Test
public void find3YoungestUsersPageableWithPageSize2Sliced() {
flushTestUsers();
User youngest1 = firstUser;
User youngest2 = fourthUser;
User youngest3 = secondUser;
Slice<User> firstPage = repository.findTop3UsersBy(new PageRequest(0, 2, ASC, "age"));
assertThat(firstPage.getContent(), hasItems(youngest1, youngest2));
Slice<User> secondPage = repository.findTop3UsersBy(new PageRequest(1, 2, ASC, "age"));
assertThat(secondPage.getContent(), hasItems(youngest3));
}
/**
* @see DATAJPA-551
*/
@Test
public void find2YoungestUsersPageableWithPageSize3Sliced() {
flushTestUsers();
User youngest1 = firstUser;
User youngest2 = fourthUser;
User youngest3 = secondUser;
Slice<User> firstPage = repository.findTop2UsersBy(new PageRequest(0, 3, ASC, "age"));
assertThat(firstPage.getContent(), hasItems(youngest1, youngest2));
Slice<User> secondPage = repository.findTop2UsersBy(new PageRequest(1, 3, ASC, "age"));
assertThat(secondPage.getContent(), hasItems(youngest3));
}
private Page<User> executeSpecWithSort(Sort sort) {
flushTestUsers();

View File

@@ -380,4 +380,69 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
*/
@Query(name = "User.findBySpringDataNamedQuery", countProjection = "u.firstname")
Page<User> findByNamedQueryAndCountProjection(String firstname, Pageable page);
/**
* @see DATAJPA-551
*/
User findFirstByOrderByAgeDesc();
/**
* @see DATAJPA-551
*/
User findFirst1ByOrderByAgeDesc();
/**
* @see DATAJPA-551
*/
User findTopByOrderByAgeDesc();
/**
* @see DATAJPA-551
*/
User findTopByOrderByAgeAsc();
/**
* @see DATAJPA-551
*/
User findTop1ByOrderByAgeAsc();
/**
* @see DATAJPA-551
*/
List<User> findTop2ByOrderByAgeDesc();
/**
* @see DATAJPA-551
*/
List<User> findFirst2ByOrderByAgeDesc();
/**
* @see DATAJPA-551
*/
List<User> findFirst2UsersBy(Sort sort);
/**
* @see DATAJPA-551
*/
List<User> findTop2UsersBy(Sort sort);
/**
* @see DATAJPA-551
*/
Page<User> findFirst3UsersBy(Pageable page);
/**
* @see DATAJPA-551
*/
Page<User> findFirst2UsersBy(Pageable page);
/**
* @see DATAJPA-551
*/
Slice<User> findTop3UsersBy(Pageable page);
/**
* @see DATAJPA-551
*/
Slice<User> findTop2UsersBy(Pageable page);
}