Check for page offsets exceeding Integer.MAX_VALUE.
Instead of relying on the JPA provider to handle page offsets exceeding Integer.MAX_VALUE, do the check inside Spring Data JPA and provide a more meaningful error message. Closes #2502.
This commit is contained in:
@@ -18,6 +18,7 @@ package org.springframework.data.jpa.repository.query;
|
||||
import jakarta.persistence.Query;
|
||||
|
||||
import org.springframework.data.jpa.repository.query.QueryParameterSetter.ErrorHandling;
|
||||
import org.springframework.data.jpa.support.PageableUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -99,7 +100,7 @@ public class ParameterBinder {
|
||||
return query;
|
||||
}
|
||||
|
||||
query.setFirstResult((int) accessor.getPageable().getOffset());
|
||||
query.setFirstResult(PageableUtils.getOffsetAsInteger(accessor.getPageable()));
|
||||
query.setMaxResults(accessor.getPageable().getPageSize());
|
||||
|
||||
return query;
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -22,9 +25,6 @@ import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -32,6 +32,7 @@ import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.repository.query.EscapeCharacter;
|
||||
import org.springframework.data.jpa.support.PageableUtils;
|
||||
import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery;
|
||||
import org.springframework.data.support.PageableExecutionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -66,8 +67,7 @@ class FetchableFluentQueryByExample<S, R> extends FluentQuerySupport<S, R> imple
|
||||
|
||||
private FetchableFluentQueryByExample(Example<S> example, Class<S> entityType, Class<R> returnType, Sort sort,
|
||||
Collection<String> properties, Function<Sort, TypedQuery<S>> finder, Function<Example<S>, Long> countOperation,
|
||||
Function<Example<S>, Boolean> existsOperation,
|
||||
EntityManager entityManager, EscapeCharacter escapeCharacter) {
|
||||
Function<Example<S>, Boolean> existsOperation, EntityManager entityManager, EscapeCharacter escapeCharacter) {
|
||||
|
||||
super(returnType, sort, properties, entityType);
|
||||
this.example = example;
|
||||
@@ -83,8 +83,8 @@ class FetchableFluentQueryByExample<S, R> extends FluentQuerySupport<S, R> imple
|
||||
|
||||
Assert.notNull(sort, "Sort must not be null!");
|
||||
|
||||
return new FetchableFluentQueryByExample<>(example, entityType, resultType, this.sort.and(sort), properties,
|
||||
finder, countOperation, existsOperation, entityManager, escapeCharacter);
|
||||
return new FetchableFluentQueryByExample<>(example, entityType, resultType, this.sort.and(sort), properties, finder,
|
||||
countOperation, existsOperation, entityManager, escapeCharacter);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,7 +168,7 @@ class FetchableFluentQueryByExample<S, R> extends FluentQuerySupport<S, R> imple
|
||||
TypedQuery<S> pagedQuery = createSortedAndProjectedQuery();
|
||||
|
||||
if (pageable.isPaged()) {
|
||||
pagedQuery.setFirstResult((int) pageable.getOffset());
|
||||
pagedQuery.setFirstResult(PageableUtils.getOffsetAsInteger(pageable));
|
||||
pagedQuery.setMaxResults(pageable.getPageSize());
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.support.PageableUtils;
|
||||
import org.springframework.data.repository.query.FluentQuery;
|
||||
import org.springframework.data.support.PageableExecutionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -170,7 +171,7 @@ class FetchableFluentQueryBySpecification<S, R> extends FluentQuerySupport<S, R>
|
||||
TypedQuery<S> pagedQuery = createSortedAndProjectedQuery();
|
||||
|
||||
if (pageable.isPaged()) {
|
||||
pagedQuery.setFirstResult((int) pageable.getOffset());
|
||||
pagedQuery.setFirstResult(PageableUtils.getOffsetAsInteger(pageable));
|
||||
pagedQuery.setMaxResults(pageable.getPageSize());
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ import org.springframework.data.jpa.repository.EntityGraph;
|
||||
import org.springframework.data.jpa.repository.query.EscapeCharacter;
|
||||
import org.springframework.data.jpa.repository.query.QueryUtils;
|
||||
import org.springframework.data.jpa.repository.support.QueryHints.NoHints;
|
||||
import org.springframework.data.jpa.support.PageableUtils;
|
||||
import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery;
|
||||
import org.springframework.data.support.PageableExecutionUtils;
|
||||
import org.springframework.data.util.ProxyUtils;
|
||||
@@ -650,7 +651,7 @@ public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T
|
||||
@Nullable Specification<S> spec) {
|
||||
|
||||
if (pageable.isPaged()) {
|
||||
query.setFirstResult((int) pageable.getOffset());
|
||||
query.setFirstResult(PageableUtils.getOffsetAsInteger(pageable));
|
||||
query.setMaxResults(pageable.getPageSize());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2008-2022 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.support;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
/**
|
||||
* Provide a set of utility methods to support interfacing {@link Pageable}s.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class PageableUtils {
|
||||
|
||||
private PageableUtils() {
|
||||
throw new IllegalStateException("Cannot instantiate a utility class!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link Pageable}'s offset value from {@link Long} to {@link Integer} to support JPA spec methods.
|
||||
*
|
||||
* @param pageable
|
||||
* @return integer
|
||||
*/
|
||||
public static int getOffsetAsInteger(Pageable pageable) {
|
||||
|
||||
if (pageable.getOffset() > Integer.MAX_VALUE) {
|
||||
throw new InvalidDataAccessApiUsageException("Page offset exceeds Integer.MAX_VALUE (" + Integer.MAX_VALUE + ")");
|
||||
}
|
||||
|
||||
return Math.toIntExact(pageable.getOffset());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user