DATAJPA-486 - Added support for sliced query execution.
Added support for Slice as return type for query methods. The execution will expand the requested page size by one to read one more element than actually requested. If that additional element is returned, it will considered to be an indicator for whether a next slice is available. Related issues: DATACMNS-397.
This commit is contained in:
@@ -25,6 +25,7 @@ import org.springframework.data.jpa.repository.query.JpaQueryExecution.Collectio
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.ModifyingExecution;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.PagedExecution;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.SingleEntityExecution;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.SlicedExecution;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -100,6 +101,8 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
|
||||
|
||||
if (method.isCollectionQuery()) {
|
||||
return new CollectionExecution();
|
||||
} else if (method.isSliceQuery()) {
|
||||
return new SlicedExecution(method.getParameters());
|
||||
} else if (method.isPageQuery()) {
|
||||
return new PagedExecution(method.getParameters());
|
||||
} else if (method.isModifyingQuery()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2013 the original author or authors.
|
||||
* Copyright 2008-2014 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.
|
||||
@@ -27,6 +27,8 @@ import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.SliceImpl;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
@@ -87,7 +89,7 @@ public abstract class JpaQueryExecution {
|
||||
protected abstract Object doExecute(AbstractJpaQuery query, Object[] values);
|
||||
|
||||
/**
|
||||
* Executes the {@link AbstractStringBasedJpaQuery} to return a simple collection of entities.
|
||||
* Executes the query to return a simple collection of entities.
|
||||
*/
|
||||
static class CollectionExecution extends JpaQueryExecution {
|
||||
|
||||
@@ -97,6 +99,47 @@ public abstract class JpaQueryExecution {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the query to return a {@link Slice} of entities.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 1.6
|
||||
*/
|
||||
static class SlicedExecution extends JpaQueryExecution {
|
||||
|
||||
private final Parameters<?, ?> parameters;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SlicedExecution} using the given {@link Parameters}.
|
||||
*
|
||||
* @param parameters must not be {@literal null}.
|
||||
*/
|
||||
public SlicedExecution(Parameters<?, ?> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jpa.repository.query.JpaQueryExecution#doExecute(org.springframework.data.jpa.repository.query.AbstractJpaQuery, java.lang.Object[])
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
|
||||
ParametersParameterAccessor accessor = new ParametersParameterAccessor(parameters, values);
|
||||
Pageable pageable = accessor.getPageable();
|
||||
|
||||
Query createQuery = query.createQuery(values);
|
||||
int pageSize = pageable.getPageSize();
|
||||
createQuery.setMaxResults(pageSize + 1);
|
||||
|
||||
List<Object> resultList = createQuery.getResultList();
|
||||
boolean hasNext = resultList.size() > pageSize;
|
||||
|
||||
return new SliceImpl<Object>(hasNext ? resultList.subList(0, pageSize) : resultList, pageable, hasNext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the {@link AbstractStringBasedJpaQuery} to return a {@link org.springframework.data.domain.Page} of
|
||||
* entities.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2011 the original author or authors.
|
||||
* Copyright 2008-2014 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.
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.jpa.repository;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.domain.Sort.Direction.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -27,8 +28,8 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
@@ -47,8 +48,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Transactional
|
||||
public class UserRepositoryFinderTests {
|
||||
|
||||
@Autowired
|
||||
UserRepository userRepository;
|
||||
@Autowired UserRepository userRepository;
|
||||
|
||||
User dave, carter, oliver;
|
||||
|
||||
@@ -136,6 +136,9 @@ public class UserRepositoryFinderTests {
|
||||
assertThat(result.get(0), is(oliver));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-92
|
||||
*/
|
||||
@Test
|
||||
public void findsByLastnameIgnoringCase() throws Exception {
|
||||
List<User> result = userRepository.findByLastnameIgnoringCase("BeAUfoRd");
|
||||
@@ -143,6 +146,9 @@ public class UserRepositoryFinderTests {
|
||||
assertThat(result.get(0), is(carter));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-92
|
||||
*/
|
||||
@Test
|
||||
public void findsByLastnameIgnoringCaseLike() throws Exception {
|
||||
List<User> result = userRepository.findByLastnameIgnoringCaseLike("BeAUfo%");
|
||||
@@ -150,6 +156,9 @@ public class UserRepositoryFinderTests {
|
||||
assertThat(result.get(0), is(carter));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-92
|
||||
*/
|
||||
@Test
|
||||
public void findByLastnameAndFirstnameAllIgnoringCase() throws Exception {
|
||||
List<User> result = userRepository.findByLastnameAndFirstnameAllIgnoringCase("MaTTheWs", "DaVe");
|
||||
@@ -157,12 +166,15 @@ public class UserRepositoryFinderTests {
|
||||
assertThat(result.get(0), is(dave));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-94
|
||||
*/
|
||||
@Test
|
||||
public void respectsPageableOrderOnQueryGenerateFromMethodName() throws Exception {
|
||||
Page<User> ascending = userRepository.findByLastnameIgnoringCase(new PageRequest(0, 10, new Sort(Direction.ASC,
|
||||
"firstname")), "Matthews");
|
||||
Page<User> descending = userRepository.findByLastnameIgnoringCase(new PageRequest(0, 10, new Sort(Direction.DESC,
|
||||
"firstname")), "Matthews");
|
||||
Page<User> ascending = userRepository.findByLastnameIgnoringCase(
|
||||
new PageRequest(0, 10, new Sort(ASC, "firstname")), "Matthews");
|
||||
Page<User> descending = userRepository.findByLastnameIgnoringCase(new PageRequest(0, 10,
|
||||
new Sort(DESC, "firstname")), "Matthews");
|
||||
assertThat(ascending.getTotalElements(), is(2L));
|
||||
assertThat(descending.getTotalElements(), is(2L));
|
||||
assertThat(ascending.getContent().get(0).getFirstname(), is(not(equalTo(descending.getContent().get(0)
|
||||
@@ -171,4 +183,15 @@ public class UserRepositoryFinderTests {
|
||||
assertThat(ascending.getContent().get(1).getFirstname(), is(equalTo(descending.getContent().get(0).getFirstname())));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-486
|
||||
*/
|
||||
@Test
|
||||
public void executesQueryToSlice() {
|
||||
|
||||
Slice<User> slice = userRepository.findSliceByLastname("Matthews", new PageRequest(0, 1, ASC, "firstname"));
|
||||
|
||||
assertThat(slice.getContent(), hasItem(dave));
|
||||
assertThat(slice.hasNext(), is(true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import javax.persistence.QueryHint;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.sample.SpecialUser;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
@@ -305,4 +306,9 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
|
||||
* @see DATAJPA-454
|
||||
*/
|
||||
List<User> findByBinaryData(byte[] data);
|
||||
|
||||
/**
|
||||
* @see DATAJPA-486
|
||||
*/
|
||||
Slice<User> findSliceByLastname(String lastname, Pageable pageable);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user