Home > OS >  Spring boot skipping and duplicating items in pagination
Spring boot skipping and duplicating items in pagination

Time:10-26

I have a Users endpoint to get all the users in MySQL sorted by a boolean value using pagination, as the number keeps growing I found out it's skipping some users and duplicating others here's some screenshots in postman where a user with the same id (95) is duplicating in 2 different pages

Also sometimes i can't find some users in all the pages

Page 2

Text

Page 3

Text

ServiceImpl

@Override
    public PagedResponse<?> findAll(UserPrincipal currentUser, int page, int size) {
        AppUtils.validatePageNumberAndSize(page, size);
//return users with 'isBoard' true first
        Pageable pageable = PageRequest.of(page, size, Sort.Direction.DESC, "isBoard");
        if (currentUser.getAuthorities().contains(new SimpleGrantedAuthority(RoleName.ROLE_ADMIN.toString()))
                || currentUser.getAuthorities().contains(new SimpleGrantedAuthority(RoleName.ROLE_SUPER_ADMIN.toString()))) {
            Page<MEUser> contentPage = userRepository.findAll(pageable);
            List<MEUser> list = contentPage.getNumberOfElements() == 0 ? Collections.emptyList() : contentPage.getContent();
            return new PagedResponse<>(list.stream()
                    .map(user -> mapToAllUsersDTO(user, new AllUserDTO()))
                    .collect(Collectors.toList()), contentPage.getNumber(), contentPage.getSize(), contentPage.getTotalElements(), contentPage.getTotalPages(), contentPage.isLast());
        } else {
            Page<MEUser> contentPage = userRepository.findByMemberTrue(pageable);
            List<MEUser> list = contentPage.getNumberOfElements() == 0 ? Collections.emptyList() : contentPage.getContent();
            return new PagedResponse<>(list.stream()
                    .map(user -> mapToAllUsersDTO(user, new AllUserDTO()))
                    .collect(Collectors.toList()), contentPage.getNumber(), contentPage.getSize(), contentPage.getTotalElements(), contentPage.getTotalPages(), contentPage.isLast());
        }
    }

CodePudding user response:

This is a database problem rather than in your code. The database does not ensure consistent results when there's multiple rows with the same value of an ordered field.

When using pagination with LIMIT and OFFSET you have to supply an order by field with unique values, so in your case you have to sort by isBoard and id to ensure consistent result.

CodePudding user response:

This is because the if condition is validating only ADMIN and SUPER_USER. user 95 may have other roles that come in else conditions. Please check once and provide the database info for Roles and Users.

CodePudding user response:

i added the id condition to the pagination:

Pageable pageable = 
  PageRequest.of(page, size, Sort.by("isBoard").descending().and(Sort.by("id")));
  • Related