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.