Limitation des résultats de requête avec JPA et Spring Data JPA

1. Introduction

Dans ce didacticiel, nous allons découvrir comment limiter les résultats des requêtes avec JPA et Spring Data JPA.

Tout d'abord, nous allons examiner la table que nous voulons interroger ainsi que la requête SQL que nous voulons reproduire.

Ensuite, nous verrons comment y parvenir avec JPA et Spring Data JPA.

Commençons!

2. Les données de test

Ci-dessous, nous avons le tableau que nous allons interroger tout au long de cet article.

La question à laquelle nous voulons répondre est: «Quel est le premier siège occupé et qui l'occupe?».

Prénom Nom de famille Numéro de siège
Jill Forgeron 50
Veille Jackson 94
Fred Bloggs 22
Ricki Bobbie 36
Siya Kolisi 85

3. Le SQL

Avec SQL, nous pouvons écrire une requête qui ressemble à ceci:

SELECT firstName, lastName, seatNumber FROM passengers ORDER BY seatNumber LIMIT 1;

4. Configuration JPA

Avec JPA, nous avons d'abord besoin d'une entité pour mapper notre table:

@Entity class Passenger { @Id @GeneratedValue @Column(nullable = false) private Long id; @Basic(optional = false) @Column(nullable = false) private String fistName; @Basic(optional = false) @Column(nullable = false) private String lastName; @Basic(optional = false) @Column(nullable = false) private int seatNumber; // constructor, getters etc. }

Ensuite, nous avons besoin d'une méthode qui encapsule notre code de requête, implémentée ici en tant que PassengerRepositoryImpl # findOrderedBySeatNumberLimitedTo (int limit) :

@Repository class PassengerRepositoryImpl { @PersistenceContext private EntityManager entityManager; @Override public List findOrderedBySeatNumberLimitedTo(int limit) { return entityManager.createQuery("SELECT p FROM Passenger p ORDER BY p.seatNumber", Passenger.class).setMaxResults(limit).getResultList(); } }

Dans notre méthode de référentiel, nous utilisons EntityManager pour créer une requête sur laquelle nous appelons la méthode setMaxResults () .

Cet appel à Query # setMaxResults aboutira finalement à l'instruction limit ajoutée au SQL généré:

select passenger0_.id as id1_15_, passenger0_.fist_name as fist_nam2_15_, passenger0_.last_name as last_nam3_15_, passenger0_.seat_number as seat_num4_15_ from passenger passenger0_ order by passenger0_.seat_number limit ?

5. Avec Spring Data JPA

Nous pouvons également générer notre SQL en utilisant Spring Data JPA.

5.1. premier ou haut

Une façon d'aborder cela est d'utiliser la dérivation de nom de méthode avec les mots-clés first ou top.

Nous pouvons, facultativement, spécifier un nombre comme taille maximale du résultat qui sera retourné. Si nous l'omettons, Spring Data JPA suppose une taille de résultat de 1.

En nous rappelant que nous voulons savoir quel est le premier siège occupé et qui l'occupe, nous pouvons l'obtenir en omettant le numéro de ces deux manières:

Passenger findFirstByOrderBySeatNumberAsc(); Passenger findTopByOrderBySeatNumberAsc();

Si nous nous limitons à un résultat d'instance, comme ci-dessus, nous pouvons également envelopper le résultat en utilisant Facultatif :

Optional findFirstByOrderBySeatNumberAsc(); Optional findTopByOrderBySeatNumberAsc();

5.2. Pageable

Alternativement, nous pouvons utiliser un objet Pageable :

Page page = repository.findAll( PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber")));

Si nous jetons un coup d'œil à l'implémentation par défaut de JpaRepository, le SimpleJpaRepository, nous pouvons voir qu'il appelle également Query # setMaxResults :

protected  Page  readPage(TypedQuery  query, Class  domainClass, Pageable pageable, @Nullable Specification  spec) { if (pageable.isPaged()) { query.setFirstResult((int) pageable.getOffset()); query.setMaxResults(pageable.getPageSize()); } return PageableExecutionUtils.getPage(query.getResultList(), pageable, () -> { return executeCountQuery(this.getCountQuery(spec, domainClass)); }); }

5.3. Comparaison

Ces deux alternatives produiront le SQL que nous recherchons:

select passenger0_.id as id1_15_, passenger0_.fist_name as fist_nam2_15_, passenger0_.last_name as last_nam3_15_, passenger0_.seat_number as seat_num4_15_ from passenger passenger0_ order by passenger0_.seat_number asc limit ?

Avec la première et la plus haute convention de préférence et la configuration de préférence Pageable .

6. Conclusion

La limitation des résultats de requête dans JPA est légèrement différente de SQL - nous n'incluons pas le mot clé limit directement dans notre JPQL.

Au lieu de cela, nous faisons simplement un appel de méthode unique à Query # maxResults ou incluons le mot-clé en premier ou en haut dans notre nom de méthode Spring Data JPA.

Comme toujours, vous pouvez trouver le code sur GitHub.