Einschränken der Abfrageergebnisse mit JPA und Spring Data JPA
1. Einführung
In diesem Tutorial gehen wir zulearn about limiting query results mitJPA undSpring Data JPA.
Zunächst sehen wir uns die Tabelle an, die wir abfragen möchten, sowie die SQL-Abfrage, die wir reproduzieren möchten.
Dann werden wir gleich untersuchen, wie dies mit JPA und Spring Data JPA erreicht werden kann.
Lass uns anfangen!
2. Die Testdaten
Unten finden Sie die Tabelle, die wir in diesem Artikel abfragen werden.
Die Frage, die wir beantworten möchten, lautet: „Was ist der erste belegte Platz und wer belegt ihn?“.
Vorname |
Nachname |
Sitznummer |
Jill |
Schmied |
50 |
Eve |
Jackson |
94 |
Fred |
Bloggs |
22 |
Ricki |
Bobbie |
36 |
Siya |
Kolisi |
85 |
3. Die SQL
Mit SQL können wir eine Abfrage schreiben, die ungefähr so aussieht:
SELECT firstName, lastName, seatNumber FROM passengers ORDER BY seatNumber LIMIT 1;
4. JPA-Setup
Mit JPA benötigen wir zuerst eine Entität, um unsere Tabelle abzubilden:
@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.
}
Als nächstes benötigen wir eine Methode, die unseren Abfragecode kapselt und hier alsPassengerRepositoryImpl#findOrderedBySeatNumberLimitedTo(int limit) implementiert ist:
@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();
}
}
In unserer Repository-Methode verwenden wirEntityManager, umQuery zu erstellen, für die wir diesetMaxResults()-Methode aufrufen.
Dieser Aufruf vonQuery#setMaxResults führt schließlich dazu, dass die Limit-Anweisung an die generierte SQL angehängt wird:
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. Mit Federdaten JPA
Wir können unsere SQL auch mit Spring Data JPA generieren.
5.1. first odertop
Eine Möglichkeit, dies zu erreichen, besteht darin, die Ableitung von Methodennamen mit den Schlüsselwörternfirst odertop. zu verwenden
Optional können wir eine Zahl als maximale Ergebnisgröße angeben, die zurückgegeben wird. Wenn wir es weglassen, geht Spring Data JPA von einer Ergebnisgröße von 1 aus.
Wenn wir uns daran erinnern, dass wir wissen möchten, was der erste Sitzplatz ist und wer ihn belegt, können wir die Nummer auf zwei Arten weglassen:
Passenger findFirstByOrderBySeatNumberAsc();
Passenger findTopByOrderBySeatNumberAsc();
Wenn wir uns wie oben auf ein Instanzergebnis beschränken, können wir das Ergebnis auch mitOptional umbrechen:
Optional findFirstByOrderBySeatNumberAsc();
Optional findTopByOrderBySeatNumberAsc();
5.2. Pageable
Alternativ können wir einPageable-Objekt verwenden:
Page page = repository.findAll(PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber")));
Wenn wir uns die Standardimplementierung vonJpaRepository, ansehen, kannSimpleJpaRepository, we sehen, dass es auchQuery#setMaxResults aufruft:
protected Page < S > readPage(TypedQuery < S > query,
Class < S > domainClass, Pageable pageable,
@Nullable Specification < S > 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. Vergleich
Beide Alternativen erzeugen die SQL, nach der wir suchen:
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 ?
Mitfirst andtopbevorzugt Konvention undPageablebevorzugt Konfiguration.
6. Fazit
Das Einschränken der Abfrageergebnisse inJPA unterscheidet sich geringfügig von SQL. Das Schlüsselwort limit wird nicht direkt in unsereJPQL aufgenommen.
Stattdessen führen wir nur einen einzelnen Methodenaufruf fürQuery#maxResults durch oder fügen das Schlüsselwortfirst odertop in unseren MethodennamenSpring Data JPAein.
Wie immer finden Sie den Codeover on GitHub.