Ein Leitfaden für Querydsl mit JPA

Ein Leitfaden für Querydsl mit JPA

1. Überblick

Querydsl ist ein umfangreiches Java-Framework, das beim Erstellen und Ausführen vontype-safe queries in a domain specific language that is similar to SQL hilft.

In diesem Artikel untersuchen wir Querydsl mit der Java Persistence API.

Eine kurze Randnotiz ist, dass HQL für Hibernate die erste Zielsprache für Querydsl war, aber heutzutage JPA, JDO, JDBC, Lucene, Hibernate Search, MongoDB, Collections und RDFBean als Backends unterstützt.

2. Vorbereitungen

Fügen wir zunächst die erforderlichen Abhängigkeiten zu unserem Maven-Projekt hinzu:


    2.5.0



    com.querydsl
    querydsl-apt
    ${querydsl.version}
    provided



    com.querydsl
    querydsl-jpa
    ${querydsl.version}



    org.slf4j
    slf4j-log4j12
    1.6.1

Und jetzt konfigurieren wir das Maven APT-Plugin:


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

DieJPAAnnotationProcessor finden Domänentypen, die mitjavax.persistence.Entity Annotation versehen sind, und generieren Abfragetypen für sie.

3. Abfragen mit Querydsl

Abfragen werden basierend auf generierten Abfragetypen erstellt, die die Eigenschaften Ihrer Domänentypen widerspiegeln. Auch Funktions- / Methodenaufrufe sind absolut typsicher aufgebaut.

Die Abfragepfade und Operationen sind in allen Implementierungen gleich und auch dieQuery-Schnittstellen haben eine gemeinsame Basisschnittstelle.

3.1. Eine Entität und der Querydsl-Abfragetyp

Definieren wir zunächst eine einfache Entität, die wir verwenden werden, wenn wir Beispiele durchgehen:

@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 generiert einen Abfragetyp mit dem einfachen NamenQPerson im selben Paket wiePerson. QPerson kann als statisch typisierte Variable in Querydsl-Abfragen als Repräsentant für den TypPerson verwendet werden.

First -QPerson hat eine Standardinstanzvariable, auf die als statisches Feld zugegriffen werden kann:

QPerson person = QPerson.person;

Alternativ können Sie Ihre eigenenPerson-Variablen wie folgt definieren:

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

3.2. Abfrage mitJPAQuery erstellen

Wir können jetztJPAQuery Instanzen für unsere Abfragen verwenden:

JPAQuery query = new JPAQuery(entityManager);

Beachten Sie, dassentityManager ein JPAEntityManager ist.

Lassen Sie uns nun alle Personen mit dem Vornamen "Kent" als schnelles Beispiel abrufen:

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

Der Aufruf vonfromdefiniert die Abfragequelle und -projektion, der Teil vonwheredefiniert den Filter undlist weist Querydsl an, alle übereinstimmenden Elemente zurückzugeben.

Wir können auch mehrere Filter verwenden:

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

Or:

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

In nativer JPQL-Form würde die Abfrage folgendermaßen geschrieben:

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

Wenn Sie die Filter mit "oder" kombinieren möchten, verwenden Sie das folgende Muster:

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

4. Bestellung und Aggregation in Querydsl

Schauen wir uns nun an, wie Reihenfolge und Aggregation in der Querydsl-Bibliothek funktionieren.

4.1. Bestellung

Zunächst ordnen wir unsere Ergebnisse in absteigender Reihenfolge nach dem Feldsurname:

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

4.2. Anhäufung

Verwenden wir jetzt eine einfache Aggregation, da einige verfügbar sind (Summe, Durchschnitt, Max, Min):

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

4.3. Aggregation mitGroupBy

Die Klassecom.mysema.query.group.GroupBy bietet Aggregationsfunktionen, mit denen wir Abfrageergebnisse im Speicher aggregieren können.

Hier ist ein kurzes Beispiel, in dem das Ergebnis alsMap mitfirstname als Schlüssel undmax age als Wert zurückgegeben wird:

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

5. Testen mit Querydsl

Definieren wir nun eine DAO-Implementierung mit Querydsl - und definieren wir die folgende Suchoperation:

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);
}

Lassen Sie uns nun einige Tests mit diesem neuen DAO erstellen und Querydsl verwenden, um nach neu erstelltenPerson-Objekten (implementiert inPersonDao-Klasse) zu suchen, und in einer anderen Testaggregation mitGroupBy-Klasse wird getestet ::

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

Dieses Tutorial zeigt, wie man ein JPA-Projekt mit Querydsl erstellt.

Diefull implementation dieses Artikels sindin the github project - dies ist ein Eclipse-basiertes Maven-Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.

Ein kurzer Hinweis hier ist: Führen Sie einen einfachen Maven-Build (mvn clean install) aus, um die Typen intarget/generated-sources zu generieren. Wenn Sie Eclipse verwenden, fügen Sie den Ordner als Quellordner des Projekts hinzu.