web-dev-qa-db-fra.com

Comment mettre en œuvre la pagination dans une botte de printemps avec hibernation

J'utilise Spring Boot avec Hibernate et je souhaite utiliser la pagination dans mon projet. J'ai cherché sur google et vu de nombreux exemples, mais je suis incapable de le mettre en œuvre dans mon projet.

Je veux comme si je passe 1 dans mon URL puis 10 résultats devraient venir et si je passe 2 puis 10 prochains résultats devraient venir et ainsi de suite.

Voici mon mon Dao

@Transactional
public interface PostDao extends CrudRepository<Post, Long>{

@Query(getAllPostsByRank)
List<Post> getAllPostsByRank();

final String getAllPostsByRank= "from Post order by value DESC";
}

Voici mon Contrôleur

@RequestMapping("/top")
    @ResponseBody 
     public List<Post> getAllPosts(HttpServletRequest req, HttpServletResponse res) throws ServletException {

List<Post> postobj = postDao.getAllPostsByRank();
return postobj;
}

Et voici mon url:

http://localhost:8888/v1.0/post/top/1

Veuillez suggérer.

12
Nadeem Ahmed

Vérifie ça. Votre contrôleur

@RequestMapping("/top/pages/{pageno}")
    @ResponseBody 
     public List<Post> getAllPosts(@PathVariable("pageno") int pageno, HttpServletRequest req, HttpServletResponse res) throws ServletException {

List<Post> postobj = postDao.getAllPostsByRank(new PageRequest(pageno,10));
return postobj;
}

Votre dao

@Transactional
public interface PostDao extends CrudRepository<Post, Long>{

@Query(getAllPostsByRank)
List<Post> getAllPostsByRank(Pageable pageable);

final String getAllPostsByRank= "from Post order by value DESC";
}
8
artle

J'envisagerais d'utiliser org.springframework.data.domain.Pageable directement dans votre contrôleur. Cet objet peut ensuite être transmis à votre couche JPA où il gérera le nombre de résultats renvoyés et la taille. 

L’avantage de l’utilisation de Pageable est qu’il renvoie un objet Page qui peut être utilisé au début pour former la logique de page précédente/suivante. 

Par défaut, cette classe utilise les paramètres url ' page ' et ' size '; Par conséquent, page = 0 & size = 10 renverra les 10 premiers éléments.

Ainsi, dans votre cas, le code pourrait ressembler à quelque chose comme:

@ResponseBody
@RequestMapping("/top/pages/")
public List<Post> getAllPosts(@PageableDefault(value=10, page=0) Pageable pageable) throws ServletException {
    Page page = postDao.findAll(pageable);
    return page.getContent();
}

Notez que l'annotation @PageableDefault sert uniquement à définir les paramètres par défaut et que ce n'est pas obligatoire.

Dans l'interface frontale, l'appel de la page suivante peut être <a href="/top/pages?page=1">Next</a>; cela renverra une liste de messages de 11 à 20. 

15
Ithar

Implémenter la pagination dans Spring Boot est assez facile, il suffit de suivre les étapes de base

1 - Étend PagingAndSortingRepository dans l'interface de référentiel

public interface UserRepository extends PagingAndSortingRepository <User, Long> 

2 - La déclaration de méthode devrait être comme ci-dessous exemple

Page<User> userList(Pageable pageable);

3 - L'implémentation de la méthode dans la classe de service devrait être comme dans l'exemple ci-dessous

@Override
public Page<User> userList(Pageable pageable) {
        return userRepository.findAll(pageable);
}

4 - Le code de classe du contrôleur devrait être comme ci-dessous

@GetMapping("/list")
public String userList(Model model, Pageable pageable) {
        Page<User> pages = userService.userList(pageable);
        model.addAttribute("number", pages.getNumber());
        model.addAttribute("totalPages", pages.getTotalPages());
        model.addAttribute("totalElements",       
                                      pages.getTotalElements());
        model.addAttribute("size", pages.getSize());
        model.addAttribute("users", pages.getContent());
        return "/user/list";
}

À partir de l'appel initial devrait être comme ci-dessous

http://localhost:8080/application/user/list?page=0&size=5
http://localhost:8080/application/user/list?page=1&size=5
http://localhost:8080/application/user/list?page=2&size=5

Pour plus de détails, regardez la vidéo ci-dessous

Spring Boot: Pagination Basic

Spring Boot: Pagination Advanced

Merci d'avoir lu

7
jeet singh parmar

Comment implémenter une pagination dynamique à l'aide d'une requête native

Vous y trouverez les couches de référentiel et de service, ainsi que votre objet de transfert de données (DTO), qui seront utilisés pour mapper notre résultat et l’envoyer à la couche contrôleur.

public interface CustomSomethingRepository {
    List<Something> findPagedResultBySomethingElseId(long somethingElseId, int offset, int limit);
}

public class SomethingRepositoryImpl implements CustomSomethingRepository {
    @Autowired
    private EntityManager em;

    @SuppressWarnings("unchecked")
    @Override
    public List<Something> findPagedResultBySomethingElseId(long somethingElseId, int offset, int limit) {
        String query = "select s.* from Something s "
                + "join somethingelse selse on selse.id = s.fk_somethingelse "
                + "where selse.id = :somethingElseId "
                + "order by selse.date";
        Query nativeQuery = em.createNativeQuery(query);
        nativeQuery.setParameter("somethingElseId", somethingElseId);
        //Paginering
        nativeQuery.setFirstResult(offset);
        nativeQuery.setMaxResults(limit);
        final List<Object[]> resultList = nativeQuery.getResultList();
        List<Something> somethingList = Lists.newArrayList();
        resultList.forEach(object -> somethingList.add(//map obj to something));
        return somethingList;
    }
}

Hibernate traduit votre requête comme suit:

SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__ FROM ( select TOP(?) t as page0_ from Something s join s.somethingelse as selse order by selse.date ) inner_query ) SELECT page0_ FROM query WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?


@Service
public class SomethingService {
    private SomethingRepository somethingRepository;
    @Autowired
    public SomethingService(SomethingRepository somethingRepository){
        this.somethingRepository = somethingRepository;
    }
    @Transactional(readOnly=true)
    public PageDto getSomething(long somethingElseId, int page, int size){
         List<Something> somethings = somethingRepository.findBySomethingElseId(somethingElseId, offset, limit);
        return new PagedResult<>(somethings
                .stream()
                .map(SomethingDto::createDto)
                .sorted(comparing(SomethingDto::getDatum))
                .collect(toList()), somethings.getTotalElements(), somethings.getTotalPages();
    }
}
@Controller
//....
public class PagedResult<T> {
    public static final long DEFAULT_OFFSET = 0;
    public static final int DEFAULT_MAX_NO_OF_ROWS = 100;
    private int offset;
    private int limit;
    private long totalElements;
    private List<T> elements;
    public PagedResult(List<T> elements, long totalElements, int offset, int limit) {
        this.elements = elements;
        this.totalElements = totalElements;
        this.offset = offset;
        this.limit = limit;
    }
    public boolean hasMore() {
        return totalElements > offset + limit;
    }
    public boolean hasPrevious() {
        return offset > 0 && totalElements > 0;
    }
    public long getTotalElements() {
        return totalElements;
    }
    public int  getOffset() {
        return offset;
    }
    public int getLimit() {
        return limit;
    }
    public List<T> getElements() {
        return elements;
    }
}

Avantages et inconvénients Avantages : Moins de requêtes SQL seront générées par rapport à l'utilisation de Spring Data. Ces requêtes complexes ne peuvent pas être écrites dans Spring Data et nous devons spécifier notre requête en tant que requête native, qui peut toujours être paginée à l'aide de cette méthodologie.

Cons : Le tableau "object" doit être mappé sur un objet Java. C'est douloureux et difficile à maintenir.

Comment implémenter la pagination OffsetLimit avec Spring Data Pour autant que je sache, il n'existe pas de support "prêt à l'emploi" pour ce dont vous avez besoin dans les référentiels Spring Data par défaut. Mais vous pouvez créer une implémentation personnalisée d'objets paginables qui prendra des paramètres de limite/décalage.

Créez un objet paginable et transmettez-le à PaginationAndSortingRepository:

public class OffsetLimitRequest implements Pageable {
    private int limit;
    private int offset;
    public OffsetLimitRequest(int offset, int limit){
        this.limit = limit;
        this.offset = offset;
    }
        @Override
    public int getPageNumber() {
        return 0;
    }
    @Override
    public int getPageSize() {
        return limit;
    }
    @Override
    public int getOffset() {
        return offset;
    }
    ....
}

Cela signifie qu'il n'est pas nécessaire de changer la couche de référentiel. Le seul changement que vous auriez besoin d’apporter consiste à modifier la couche service, comme suit:

@Service
public class SomethingService {
    private SomethingRepository somethingRepository;
    @Autowired
    public SomethingService(SomethingRepository somethingRepository){
        this.somethingRepository = somethingRepository;
    }
    @Transactional(readOnly=true)
    public PageDto getSomething(long somethingElseId, int page, int size){
        Page<Something> somethings = somethingRepository.findBySomethingElseId(somethingElseId, new OffsetLimitRequest(offset, limit));
        return new PageDto(somethings.getContent()
                .stream()
                .map(SomethingDto::createDto)
                .sorted(comparing(SomethingDto::getDatum))
                .collect(toList()), somethings.getTotalElements(), somethings.getTotalPages();
    }
}

Notez que vous n'avez pas besoin de mapper le résultat manuellement et cela prendra beaucoup de temps à partir du développement.

0