Metodi di query derivati ​​nei repository JPA di Spring Data

1. Introduzione

Per query semplici, è facile ricavare quale dovrebbe essere la query semplicemente guardando il nome del metodo corrispondente nel nostro codice.

In questo tutorial, esploreremo come Spring Data JPA sfrutta questa idea sotto forma di una convenzione di denominazione dei metodi.

2. Struttura dei metodi di query derivati ​​in primavera

I nomi dei metodi derivati ​​hanno due parti principali separate dalla prima parola chiave By :

List findByName(String name)

La prima parte - come find - è l' introduttore e il resto - come ByName - è il criterio.

Spring Data JPA supporta la ricerca, la lettura, la query, il conteggio e il recupero . Quindi, ad esempio, avremmo potuto eseguire queryByName e Spring Data si sarebbe comportato allo stesso modo.

Possiamo anche utilizzare Distinct, First o Top per rimuovere i duplicati o limitare il nostro set di risultati:

List findTop3ByAge()

La parte dei criteri contiene le espressioni delle condizioni specifiche dell'entità della query. Possiamo utilizzare le parole chiave della condizione insieme ai nomi delle proprietà dell'entità. Possiamo anche concatenare le espressioni con And e Or, come ben vediamo in un attimo.

3. Applicazione di esempio

Innanzitutto, ovviamente, avremo bisogno di un'applicazione che utilizzi Spring Data JPA.

In quell'applicazione, definiamo una classe di entità:

@Table(name = "users") @Entity class User { @Id @GeneratedValue private Integer id; private String name; private Integer age; private ZonedDateTime birthDate; private Boolean active; // standard getters and setters }

E definiamo anche un repository. Estenderà JpaRepository, uno dei tipi di Spring Data Repository:

interface UserRepository extends JpaRepository {}

Qui è dove posizioneremo tutti i nostri metodi di query derivati.

4. Parole chiave della condizione di uguaglianza

L'uguaglianza esatta è una delle condizioni più utilizzate nelle query. Abbiamo diverse opzioni per esprimere gli operatori = o IS nella query.

Possiamo semplicemente aggiungere il nome della proprietà senza alcuna parola chiave per una condizione di corrispondenza esatta:

List findByName(String name);

E possiamo aggiungere Is o Equals per la leggibilità:

List findByNameIs(String name); List findByNameEquals(String name);

Questa leggibilità extra è utile quando dobbiamo esprimere invece la disuguaglianza:

List findByNameIsNot(String name);

Questo è un po 'più leggibile di findByNameNot (String) !

Poiché l' uguaglianza nulla è un caso speciale, non dovremmo usare l'operatore =. Spring Data JPA gestisce i parametri null per impostazione predefinita. Quindi, quando passiamo un valore null per una condizione di uguaglianza, Spring interpreta la query come IS NULL nell'SQL generato.

Possiamo anche utilizzare la parola chiave IsNull per aggiungere criteri IS NULL alla query:

List findByNameIsNull(); List findByNameIsNotNull();

Notare che né IsNullIsNotNull richiedono un argomento del metodo.

Ci sono anche altre due parole chiave che non richiedono argomenti. Possiamo utilizzare le parole chiave True e False per aggiungere condizioni di uguaglianza per i tipi booleani :

List findByActiveTrue(); List findByActiveFalse();

Certo, a volte vogliamo qualcosa di più indulgente dell'uguaglianza esatta, vediamo cos'altro possiamo fare.

5. Parole chiave della condizione di somiglianza

Quando abbiamo bisogno di interrogare i risultati con uno schema di una proprietà, abbiamo alcune opzioni.

Possiamo trovare nomi che iniziano con un valore utilizzando StartingWith :

List findByNameStartingWith(String prefix);

Approssimativamente, questo si traduce in "WHERE name LIKE 'value%' ".

Se vogliamo nomi che terminano con un valore, allora EndingWith è ciò che vogliamo:

List findByNameEndingWith(String suffix);

Oppure, possiamo trovare quali nomi contengono un valore con Contenente :

List findByNameContaining(String infix);

Notare che tutte le condizioni precedenti sono chiamate espressioni di pattern predefinite. Quindi, non è necessario aggiungere l' operatore % all'interno dell'argomento quando vengono chiamati questi metodi.

Ma supponiamo di fare qualcosa di più complesso. Supponiamo di dover recuperare gli utenti i cui nomi iniziano con a , contengono be terminano con c.

Per questo, possiamo aggiungere il nostro LIKE con la parola chiave Like :

List findByNameLike(String likePattern);

E possiamo quindi consegnare il nostro modello LIKE quando chiamiamo il metodo:

String likePattern = "a%b%c"; userRepository.findByNameLike(likePattern);

Per ora basta con i nomi. Proviamo alcuni altri valori in Utente.

6. Parole chiave delle condizioni di confronto

Inoltre, possiamo utilizzare le parole chiave LessThan e LessThanEqual per confrontare i record con il valore specificato utilizzando gli operatori < e <= :

List findByAgeLessThan(Integer age); List findByAgeLessThanEqual(Integer age);

On the other hand, in the opposite situation, we can use GreaterThan and GreaterThanEqual keywords:

List findByAgeGreaterThan(Integer age); List findByAgeGreaterThanEqual(Integer age);

Or, we can find users who are between two ages with Between:

List findByAgeBetween(Integer startAge, Integer endAge);

We can also supply a collection of ages to match against using In:

List findByAgeIn(Collection ages);

Since we know the users' birthdates, we might want to query for users who were born before or after a given date. We'd use Before and After for that:

List findByBirthDateAfter(ZonedDateTime birthDate); List findByBirthDateBefore(ZonedDateTime birthDate);

7. Multiple Condition Expressions

We can combine as many expressions as we need by using And and Or keywords:

List findByNameOrBirthDate(String name, ZonedDateTime birthDate); List findByNameOrBirthDateAndActive(String name, ZonedDateTime birthDate, Boolean active);

The precedence order is And then Or, just like Java.

While Spring Data JPA imposes no limit to how many expressions we can add, we shouldn't go crazy here. Long names are unreadable and hard to maintain. For complex queries, take a look at the @Query annotation instead.

8. Sorting the Results

Next up is sorting. We could ask that the users be sorted alphabetically by their name using OrderBy:

List findByNameOrderByName(String name); List findByNameOrderByNameAsc(String name);

Ascending order is the default sorting option, but we can use Desc instead to sort them in reverse:

List findByNameOrderByNameDesc(String name);

9. findOne vs findById in a CrudRepository

The Spring team made some major changes in CrudRepository with Spring Boot 2.x. One of them is renaming findOne to findById.

Previously with Spring Boot 1.x, we'd call findOne when we wanted to retrieve an entity by its primary key:

User user = userRepository.findOne(1);

Since Spring Boot 2.x we can do the same with findById:

User user = userRepository.findById(1);

Note that the findById() method is already defined in CrudRepository for us. So we don't have to define it explicitly in custom repositories that extend CrudRepository.

10. Conclusion

In questo articolo, abbiamo spiegato il meccanismo di derivazione delle query in Spring Data JPA. Abbiamo utilizzato le parole chiave della condizione della proprietà per scrivere metodi di query derivati ​​nei repository JPA Spring Data.

Il codice sorgente di questo tutorial è disponibile nel progetto Github.