public class ExtendedAuthorRepositoryImpl implements ExtendedAuthorRepository {
@PersistenceContext protected EntityManager entityManager;
@Override
public Page findAuthorsWithSoldBooks(
String queryExpression, String sortExpression, @NonNull Pageable pageable) {
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery query = builder.createQuery(AuthorDAO.class);
final Root root = query.from(AuthorDAO.class);
final Join book =
root.join(AuthorDAO_.BOOKS, JoinType.INNER);
final List predicates = new ArrayList();
predicates.add(builder.greaterThan(book.get("soldCount"), 0));
// fetch the authors as per the page limit
final List result =
entityManager
.createQuery(query)
.setFirstResult((int) pageable.getOffset())
.setMaxResults(pageable.getPageSize())
.getResultList();
// create count query
final CriteriaQuery countQuery = builder.createQuery(Long.class);
final Root rootCount = countQuery.from(AuthorDAO.class);
countQuery
.select(builder.count(rootCount))
.where(builder.and(predicates.toArray(new Predicate[predicates.size()])));
// fetch the count of all authors as per given criteria
final Long authorCount = entityManager.createQuery(countQuery).getSingleResult();
// return the page
return new PageImpl(result, pageable, authorCount);
}
Вот запрос, сгенерированный Hibernate (я запускал его в SQL Developer, и он работал как положено):
select
c1_0.id,
c1_0.name,
c1_0.surname,
c1_0.birth_date,
c1_0.biography
from author c1_0
join book c2_0 on c1_0.id=c2_0.author_id
where c2_0.sold_count > 0
offset ? rows fetch first ? rows only
Вот результат приведенного выше запроса в SQL Developer:
1 John Smith 1970-08-08 Biography 1
2 Peter Williams 1966-01-15 Biography 2
3 Arthur Mitchel 1981-04-22 Biography 3
4 Dave Bronson 1988-09-01 Biography 4
Наконец, в своем тесте я попытался получить 2 страницы размера 2:
final int pageSize = 2;
final int totalPages = 2;
final List content = IntStream.range(0, totalPages)
.mapToObj(page -> authorApi.getAuthorsWithSoldBooks(null, null, page, pageSize))
.map(AuthorsPaged::getContent)
.flatMap(List::stream)
.toList();
assertThat(content).hasSize(4); // this fails as content has size 3
Проблема в том, что при первом вызове findAuthorsWithSoldBooks() getResultList() возвращает только первую запись
- 1 John Smith
- 1 John Smith
- 2 Peter Williams
- 1 John Smith
- 2 Peter Williams
- 3 Arthur Mitchel
- 4 Dave Bronson
ОБНОВЛЕНИЕ
Вот источник автораApi.getAuthorsWithSoldBooks:
public AuthorsPaged getAuthorsWithSoldBooks(
final String queryExpression,
final String sortExpression,
final Integer page,
final Integer size) {
final Page AuthorPage = authorRepository.findAuthorsWithSoldBooks(
queryExpression,
sortExpression,
PageRequest.of(page, size));
return authorConverter.convert(AuthorPage);
}
Подробнее здесь: https://stackoverflow.com/questions/789 ... rong-pages