DATAJPA-257 - Make count query execution in SimpleJpaRepository more robust.

The execution of a count query can potentially return multiple values instead of just a single one. This causes persistence providers to throw an exception as we trigger ….getSingleResult() in SimpleJpaRepository. We're now calling …getResultList() and sum up all values returned.
This commit is contained in:
Oliver Gierke
2012-09-21 12:06:34 +02:00
parent 89dc3261f5
commit fca2516619
3 changed files with 25 additions and 2 deletions

View File

@@ -97,6 +97,7 @@ public abstract class JpaQueryExecution {
// Execute query to compute total
TypedQuery<Long> projection = repositoryQuery.createCountQuery(values);
List<Long> totals = projection.getResultList();
Long total = totals.size() == 1 ? totals.get(0) : totals.size();
@@ -160,4 +161,4 @@ public abstract class JpaQueryExecution {
return result;
}
}
}
}

View File

@@ -27,6 +27,7 @@ import java.util.regex.Pattern;
import javax.persistence.EntityManager;
import javax.persistence.Parameter;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.From;
@@ -270,6 +271,26 @@ public abstract class QueryUtils {
return orders;
}
/**
* Executes a count query and transparently sums up all values returned.
*
* @param query must not be {@literal null}.
* @return
*/
public static Long executeCountQuery(TypedQuery<Long> query) {
Assert.notNull(query);
List<Long> totals = query.getResultList();
Long total = 0L;
for (Long element : totals) {
total += element == null ? 0 : element;
}
return total;
}
/**
* Creates a criteria API {@link javax.persistence.criteria.Order} from the given {@link Order}.
*

View File

@@ -40,6 +40,7 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.query.QueryUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
@@ -402,7 +403,7 @@ public class SimpleJpaRepository<T, ID extends Serializable> implements JpaRepos
query.setFirstResult(pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
Long total = getCountQuery(spec).getSingleResult();
Long total = QueryUtils.executeCountQuery(getCountQuery(spec));
List<T> content = total > pageable.getOffset() ? query.getResultList() : Collections.<T> emptyList();
return new PageImpl<T>(content, pageable, total);