Una guida a Querydsl con JPA

1. Panoramica

Querydsl è un vasto framework Java, che aiuta a creare ed eseguire query indipendenti dai tipi in un linguaggio specifico del dominio simile a SQL .

In questo articolo esploreremo Querydsl con l'API Java Persistence.

Una breve nota a margine qui è che HQL per Hibernate è stato il primo linguaggio di destinazione per Querydsl, ma al giorno d'oggi supporta JPA, JDO, JDBC, Lucene, Hibernate Search, MongoDB, Collections e RDFBean come backend.

2. Preparativi

Aggiungiamo prima le dipendenze necessarie nel nostro progetto Maven:

 2.5.0   com.querydsl querydsl-apt ${querydsl.version} provided   com.querydsl querydsl-jpa ${querydsl.version}   org.slf4j slf4j-log4j12 1.6.1 

E ora configuriamo il plug-in APT Maven:

   ...  com.mysema.maven apt-maven-plugin 1.1.3    process   target/generated-sources com.querydsl.apt.jpa.JPAAnnotationProcessor     ...   

Il JPAAnnotationProcessor troverà tipi di dominio annotate con javax.persistence.Entity annotazioni e genera tipi di query per loro.

3. Query con Querydsl

Le query vengono costruite in base ai tipi di query generati che riflettono le proprietà dei tuoi tipi di dominio. Anche le invocazioni di funzioni / metodi sono costruite in modo completamente indipendente dai tipi.

I percorsi e le operazioni delle query sono gli stessi in tutte le implementazioni e anche le interfacce Query hanno un'interfaccia di base comune.

3.1. Un'entità e il tipo di query Querydsl

Definiamo prima un'entità semplice che utilizzeremo mentre esaminiamo gli esempi:

@Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column private String firstname; @Column private String surname; Person() { } public Person(String firstname, String surname) { this.firstname = firstname; this.surname = surname; } // standard getters and setters }

Querydsl genererà un tipo di query con il nome semplice QPerson nello stesso pacchetto di Person . QPerson può essere utilizzato come variabile tipizzata staticamente nelle query Querydsl come rappresentante per il tipo Person .

Primo: QPerson ha una variabile di istanza predefinita a cui è possibile accedere come campo statico:

QPerson person = QPerson.person;

In alternativa puoi definire le tue variabili Person in questo modo:

QPerson person = new QPerson("Erich", "Gamma");

3.2. Crea query utilizzando JPAQuery

Ora possiamo utilizzare le istanze JPAQuery per le nostre query:

JPAQuery query = new JPAQuery(entityManager);

Notare che entityManager è un EntityManager JPA .

Recuperiamo ora tutte le persone con il nome " Kent " come un rapido esempio:

QPerson person = QPerson.person; List persons = query.from(person).where(person.firstName.eq("Kent")).list(person);

La chiamata from definisce l'origine e la proiezione della query, la parte where definisce il filtro e l' elenco indica a Querydsl di restituire tutti gli elementi corrispondenti.

Possiamo anche utilizzare più filtri:

query.from(person).where(person.firstName.eq("Kent"), person.surname.eq("Beck"));

O:

query.from(person).where(person.firstName.eq("Kent").and(person.surname.eq("Beck")));

Nel formato JPQL nativo la query verrebbe scritta in questo modo:

select person from Person as person where person.firstName = "Kent" and person.surname = "Beck"

Se desideri combinare i filtri tramite "o", utilizza il seguente schema:

query.from(person).where(person.firstName.eq("Kent").or(person.surname.eq("Beck")));

4. Ordinamento e aggregazione in Querydsl

Diamo ora uno sguardo a come funzionano l'ordinamento e l'aggregazione all'interno della libreria Querydsl.

4.1. Ordinazione

Inizieremo ordinando i nostri risultati in ordine decrescente in base al campo del cognome :

QPerson person = QPerson.person; List persons = query.from(person) .where(person.firstname.eq(firstname)) .orderBy(person.surname.desc()) .list(person);

4.2. Aggregazione

Usiamo ora una semplice aggregazione, poiché ne abbiamo alcuni disponibili (Sum, Avg, Max, Min):

QPerson person = QPerson.person; int maxAge = query.from(person).list(person.age.max()).get(0);

4.3. Aggregazione con GroupBy

La classe com.mysema.query.group.GroupBy fornisce funzionalità di aggregazione che possiamo utilizzare per aggregare i risultati delle query in memoria.

Ecco un rapido esempio in cui il risultato viene restituito come mappa con firstname come chiave e max age come valore:

QPerson person = QPerson.person; Map results = query.from(person).transform( GroupBy.groupBy(person.firstname).as(GroupBy.max(person.age)));

5. Test con Querydsl

Ora definiamo un'implementazione DAO usando Querydsl e definiamo la seguente operazione di ricerca:

public List findPersonsByFirstnameQuerydsl(String firstname) { JPAQuery query = new JPAQuery(em); QPerson person = QPerson.person; return query.from(person).where(person.firstname.eq(firstname)).list(person); }

E ora costruiamo alcuni test usando questo nuovo DAO e usiamo Querydsl per cercare oggetti Person di nuova creazione (implementati nella classe PersonDao ) e in un'altra aggregazione di test usando la classe GroupBy viene testato:

@Autowired private PersonDao personDao; @Test public void givenExistingPersons_whenFindingPersonByFirstName_thenFound() { personDao.save(new Person("Erich", "Gamma")); Person person = new Person("Kent", "Beck"); personDao.save(person); personDao.save(new Person("Ralph", "Johnson")); Person personFromDb = personDao.findPersonsByFirstnameQuerydsl("Kent").get(0); Assert.assertEquals(person.getId(), personFromDb.getId()); } @Test public void givenExistingPersons_whenFindingMaxAgeByName_thenFound() { personDao.save(new Person("Kent", "Gamma", 20)); personDao.save(new Person("Ralph", "Johnson", 35)); personDao.save(new Person("Kent", "Zivago", 30)); Map maxAge = personDao.findMaxAgeByName(); Assert.assertTrue(maxAge.size() == 2); Assert.assertSame(35, maxAge.get("Ralph")); Assert.assertSame(30, maxAge.get("Kent")); }

6. Conclusione

Questo tutorial ha illustrato come creare un progetto JPA utilizzando Querydsl.

L' implementazione completa di questo articolo può essere trovata nel progetto github: questo è un progetto maven basato su Eclipse, quindi dovrebbe essere facile da importare ed eseguire così com'è.

Una breve nota qui è: esegui una semplice build maven (mvn clean install) per generare i tipi in target / generated-sources - e quindi, se stai usando Eclipse - includi la cartella come cartella di origine del progetto.