Ignore offset for if it defaults to 0.

Avoid calling `Query.setFirstResult(0)` which maybe generated sql contains unwanted `offset 0` when using query methods accepting `Limit` .

Closes #3242
Original pull request: #3454
This commit is contained in:
Yanming Zhou
2024-04-28 15:41:06 +08:00
committed by Mark Paluch
parent 8bade4e0a4
commit d14899f16b
2 changed files with 49 additions and 1 deletions

View File

@@ -30,6 +30,7 @@ import org.springframework.util.Assert;
* @author Mark Paluch
* @author Christoph Strobl
* @author Jens Schauder
* @author Yanming Zhou
*/
public class ParameterBinder {
@@ -101,7 +102,11 @@ public class ParameterBinder {
return query;
}
query.setFirstResult(PageableUtils.getOffsetAsInteger(accessor.getPageable()));
// see #3242
if (!parameters.hasLimitParameter()) {
// offset is meaningless if Limit parameter present
query.setFirstResult(PageableUtils.getOffsetAsInteger(accessor.getPageable()));
}
query.setMaxResults(accessor.getPageable().getPageSize());
return query;

View File

@@ -39,6 +39,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.data.domain.Limit;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.Temporal;
@@ -53,6 +54,7 @@ import org.springframework.data.repository.query.ParametersSource;
* @author Thomas Darimont
* @author Jens Schauder
* @author Mark Paluch
* @author Yanming Zhou
*/
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
@@ -86,6 +88,8 @@ class ParameterBinderUnitTests {
User validWithPageable(@Param("username") String username, Pageable pageable);
User validWithLimit(@Param("username") String username, Limit limit);
User validWithSort(@Param("username") String username, Sort sort);
User validWithDefaultTemporalTypeParameter(@Temporal Date registerDate);
@@ -122,6 +126,40 @@ class ParameterBinderUnitTests {
verify(query).setParameter(eq(1), eq("foo"));
}
@Test
void bindAndPrepareWorksWithPageable() throws Exception {
Method validWithPageable = SampleRepository.class.getMethod("validWithPageable", String.class, Pageable.class);
Object[] values = { "foo", Pageable.ofSize(10).withPage(3) };
bindAndPrepare(validWithPageable, values);
verify(query).setParameter(eq(1), eq("foo"));
verify(query).setFirstResult(eq(30));
verify(query).setMaxResults(eq(10));
}
@Test
void bindWorksWithNullForLimit() throws Exception {
Method validWithLimit = SampleRepository.class.getMethod("validWithLimit", String.class, Limit.class);
Object[] values = { "foo", null };
bind(validWithLimit, values);
verify(query).setParameter(eq(1), eq("foo"));
}
@Test
void bindAndPrepareWorksWithLimit() throws Exception {
Method validWithLimit = SampleRepository.class.getMethod("validWithLimit", String.class, Limit.class);
Object[] values = { "foo", Limit.of(10) };
bindAndPrepare(validWithLimit, values);
verify(query).setParameter(eq(1), eq("foo"));
verify(query).setMaxResults(eq(10));
verify(query, never()).setFirstResult(anyInt());
}
@Test
void usesIndexedParametersIfNoParamAnnotationPresent() {
@@ -236,6 +274,11 @@ class ParameterBinderUnitTests {
getAccessor(method, values), QueryParameterSetter.ErrorHandling.STRICT);
}
private void bindAndPrepare(Method method, Object[] values) {
ParameterBinderFactory.createBinder(createParameters(method)).bindAndPrepare(query,
new QueryParameterSetter.QueryMetadata(query), getAccessor(method, values));
}
private JpaParametersParameterAccessor getAccessor(Method method, Object... values) {
return new JpaParametersParameterAccessor(createParameters(method), values);
}