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.