Limitazione dei risultati delle query con JPA e Spring Data JPA

1. Introduzione

In questo tutorial impareremo a limitare i risultati delle query con JPA e Spring Data JPA.

Per prima cosa, daremo un'occhiata alla tabella che vogliamo interrogare e alla query SQL che vogliamo riprodurre.

Quindi ci immergeremo direttamente su come ottenerlo con JPA e Spring Data JPA.

Iniziamo!

2. I dati del test

Di seguito abbiamo la tabella che interrogheremo in questo articolo.

La domanda a cui vogliamo rispondere è: "Qual è il primo posto occupato e chi lo occupa?".

Nome di battesimo Cognome Numero del posto
Jill fabbro 50
vigilia Jackson 94
Fred Bloggs 22
Ricki Bobbie 36
Siya Kolisi 85

3. L'SQL

Con SQL potremmo scrivere una query simile a questa:

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

4. Configurazione JPA

Con JPA, abbiamo prima bisogno di un'entità, per mappare la nostra tabella:

@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. }

Successivamente abbiamo bisogno di un metodo che incapsuli il nostro codice di query, implementato qui come 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(); } }

Nel nostro metodo di repository, utilizziamo EntityManager per creare una query su cui chiamiamo il metodo setMaxResults () .

Questa chiamata a Query # setMaxResults risulterà infine nell'istruzione limit aggiunta all'SQL generato:

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. Con Spring Data JPA

Possiamo anche generare il nostro SQL utilizzando Spring Data JPA.

5.1. primo o in alto

Un modo in cui potremmo affrontarlo è utilizzare la derivazione del nome del metodo con le parole chiave first o top.

Facoltativamente, possiamo specificare un numero come dimensione massima del risultato che verrà restituito. Se lo omettiamo, Spring Data JPA assume una dimensione del risultato di 1.

Ricordando che vogliamo sapere qual è il primo posto occupato e chi lo sta occupando, possiamo ottenerlo omettendo il numero in questi due modi:

Passenger findFirstByOrderBySeatNumberAsc(); Passenger findTopByOrderBySeatNumberAsc();

Se ci limitiamo a un risultato di istanza, come sopra, possiamo anche racchiudere il risultato utilizzando Opzionale :

Optional findFirstByOrderBySeatNumberAsc(); Optional findTopByOrderBySeatNumberAsc();

5.2. Paginabile

In alternativa, possiamo usare un oggetto Pageable :

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

Se diamo un'occhiata all'implementazione predefinita di JpaRepository, il SimpleJpaRepository, possiamo vedere che chiama anche 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. Confronto

Entrambe queste alternative produrranno l'SQL che stiamo cercando:

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 ?

Con la convenzione di primo e primo favore e la configurazione di favore pagabile .

6. Conclusione

La limitazione dei risultati delle query in JPA è leggermente diversa da SQL: non includiamo la parola chiave limit direttamente nel nostro JPQL.

Invece, facciamo solo una singola chiamata al metodo Query # maxResults o includiamo la parola chiave prima o in cima al nostro nome del metodo JPA Spring Data.

Come sempre, puoi trovare il codice su GitHub.