← Notizen

Querydsl-Q-Typen mit Spring Boot 3 und Jakarta erzeugen

Auf dieser Seite

Um Querydsl-JPA-Q-Typen unter Spring Boot 3 zu erzeugen, stimmen Sie Versionen und jakarta-Classifier von querydsl-jpa und querydsl-apt aufeinander ab, konfigurieren die Annotation-Verarbeitung und prüfen anschließend einen sauberen Build sowie einen Datenbankabfragetest. Die Versionshinweise zu 5.0 dokumentieren die Jakarta-Classifier-Unterstützung. Mit Gradles Standardpfaden für generierte Quellen vermeiden Sie, dass Haupt- und Testkompilierung in dasselbe Verzeichnis schreiben.

Dieser Leitfaden erweitert das ursprüngliche koreanische Beispiel aus 2023 zu einer ausführbaren Konfiguration. Die folgenden Versionen fixieren die Reproduktionsumgebung; sie sind keine Empfehlung aktueller Produktionsabhängigkeiten.

Verarbeitungsablauf

Q-Typen erzeugen und Abfrage ausführen

Der Prozessor erzeugt QEmployee während der Hauptkompilierung. Der H2-Test führt anschließend eine Abfrage mit diesen generierten Typen aus.

Reproduktionsumgebung und vollständige Gradle-Einrichtung

Komponente Reproduktionsversion
JDK / Gradle 17.0.8.1 / 8.4
Spring Boot BOM 3.5.7
Querydsl JPA / APT 5.1.0, beide mit dem jakarta-Classifier
Hibernate / H2 6.6.33.Final / 2.3.232, durch die BOM verwaltet

Erstellen Sie diese fünf Dateien in einem neuen Verzeichnis. Dieses Testprojekt verwendet das Java-Plugin und die Boot-BOM; das Boot-Gradle-Plugin benötigt es nicht. Ergänzen Sie in einer bestehenden Boot-Anwendung nur die benötigten Abhängigkeiten neben der gewählten Abhängigkeitsverwaltung.

settings.gradle

rootProject.name = 'querydsl-jakarta-example'

build.gradle

plugins { id 'java' }
repositories { mavenCentral() }
dependencies {
    implementation platform('org.springframework.boot:spring-boot-dependencies:3.5.7')
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'com.querydsl:querydsl-jpa:5.1.0:jakarta'

    annotationProcessor platform('org.springframework.boot:spring-boot-dependencies:3.5.7')
    annotationProcessor 'com.querydsl:querydsl-apt:5.1.0:jakarta'
    annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
    annotationProcessor 'jakarta.annotation:jakarta.annotation-api'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'com.h2database:h2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
test { useJUnitPlatform() }

Gradle löst annotationProcessor getrennt von den normalen Kompilier- und Laufzeitklassenpfaden auf. Das Beispiel wendet die BOM daher auch auf die Prozessorkonfiguration an und stellt die Jakarta Persistence- und Annotation-APIs ausdrücklich bereit. Eine Abhängigkeit unter implementation steht dem Prozessor nicht automatisch zur Verfügung. Siehe die Dokumentation des Gradle-Java-Plugins.

Anwendung und Entität erstellen

Über die Anwendungsklasse findet der JPA-Test seine Boot-Konfiguration. Für den Test muss kein separater Serverprozess gestartet werden.

src/main/java/example/Application.java

package example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

src/main/java/example/Employee.java

package example;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    public String getName() { return name; }

    protected Employee() {}

    public Employee(String name) {
        this.name = name;
    }
}

Employee verwendet jakarta.persistence. Schreiben Sie QEmployee nicht selbst: Der Annotation-Prozessor erzeugt den im folgenden Test referenzierten Typ.

Über den generierten Q-Typ abfragen

src/test/java/example/EmployeeQueryTest.java

package example;

import com.querydsl.jpa.impl.JPAQueryFactory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;

import static org.assertj.core.api.Assertions.assertThat;

@DataJpaTest
class EmployeeQueryTest {
    @Autowired
    private TestEntityManager entityManager;

    @Test
    void findsEmployeeByName() {
        entityManager.persistAndFlush(new Employee("Alice"));
        entityManager.persistAndFlush(new Employee("Bob"));
        QEmployee employee = QEmployee.employee;
        var names = new JPAQueryFactory(entityManager.getEntityManager())
            .select(employee.name).from(employee)
            .where(employee.name.eq("Alice")).fetch();
        assertThat(names).containsExactly("Alice");
    }

    @Test
    void returnsNoRowsForMissingName() {
        entityManager.persistAndFlush(new Employee("Alice"));
        QEmployee employee = QEmployee.employee;
        var names = new JPAQueryFactory(entityManager.getEntityManager())
            .select(employee.name).from(employee)
            .where(employee.name.eq("Missing")).fetch();
        assertThat(names).isEmpty();
    }
}

@DataJpaTest verwendet H2 aus dem Klassenpfad dieses Beispiels. Jeder Test läuft in einer Transaktion, die danach zurückgerollt wird. Nach dem Einfügen der Daten mit persistAndFlush ermöglicht das generierte QEmployee zwei Prüfungen: eine exakte Namensübereinstimmung und eine Abfrage ohne Ergebniszeilen. Siehe Spring Boots Leitfaden zu JPA-Tests.

Diese Tests prüfen diese Entität und Abfrage auf H2. Sie prüfen weder SQL-Dialekt, Sortierregeln, Sperren noch Migrationsverhalten Ihrer Produktionsdatenbank.

Ausführen und generierte Dateien prüfen

Wählen Sie JDK 17 und verwenden Sie ein installiertes Gradle 8.4. Führen Sie im Projektstamm Folgendes aus:

java -version
gradle --version
gradle --no-daemon clean test

Prüfen Sie diese generierten Artefakte und den Testbericht:

build/generated/sources/annotationProcessor/java/main/example/QEmployee.java
build/classes/java/main/example/QEmployee.class
build/reports/tests/test/index.html

Beide Tests bestanden mit dieser Konfiguration. Eine Wiederholung von clean test erzeugte den Q-Typ neu und ließ beide Tests erneut bestehen. Verwenden Sie bei einem bestehenden Projekt mit Gradle Wrapper dessen ausgewählte Version über ./gradlew clean test.

Der generierte Q-Typ dieses Beispiels importiert javax.annotation.processing.Generated, eine Java-SE-API aus java.compiler. Dieser Import benötigt keinen Jakarta-Ersatz. Generated-API des JDK 17.

Warum fehlen Q-Typen oder werden doppelt erzeugt?

Symptom Erste Prüfung
QEmployee wird nicht gefunden CLI-Ergebnis von clean compileJava, Prozessorabhängigkeiten und jakarta.persistence-Imports der Entität prüfen.
Der Prozessor findet Persistence-APIs nicht Prüfen, ob die nötigen Jakarta-APIs getrennt vom normalen Klassenpfad auf dem Prozessorpfad liegen.
Ein inkompatibler Typ javax.persistence.EntityManager erscheint Übereinstimmende Versionen und Jakarta-Classifier beider Querydsl-Artefakte prüfen.
Doppelte Q-Typen oder ein Build, der nur nach clean funktioniert Manuell geschriebene Q-Quellen und gemeinsame Generierungspfade entfernen; Ausgabekonfiguration für Haupt- und Testquellen prüfen.
CLI funktioniert, aber die IDE sieht keine Q-Typen Gradle-Synchronisierung, delegierte Build-Einstellungen und Annotation-Verarbeitung der IDE prüfen.

Das Beispiel ergänzt keine benutzerdefinierte Konfiguration von sourceSets, JavaCompile oder clean für generierte Dateien. Falls Sie einen eigenen Pfad benötigen, halten Sie Haupt- und Testausgaben getrennt. configureEach steuert die verzögerte Aufgabenkonfiguration; es behebt keine Jakarta-Abhängigkeitsinkompatibilität. Gradle-Konfigurationsvermeidung.

Für den umgebenden Upgrade-Ablauf siehe den Spring-Boot-3-Migrationsleitfaden. Für ausgehende HTTP-Grenzen verwenden Sie die WebClient- und MockWebServer-Tests.

Vor einem Wechsel der Abfragewerkzeuge vergleichen

Die vollständige Employee-Klasse enthält einen Getter, damit sich Repository-Ergebnisse anhand der Namen vergleichen lassen. Ergänzen Sie die drei Dateien aus dem Vergleich von Querydsl und Specification, um acht weitere Prüfungen derselben Entität auszuführen. Die beiden ursprünglichen Tests oben bleiben Teil dieses Projekts mit zehn Tests. Verglichen werden ausgewählte H2-Prädikate, nicht das gesamte Datenbankverhalten. Der Spring-Boot-Leitfaden verbindet die umgebenden Einrichtungs- und Testschritte.

Diskussion

Auf GitHub ansehen ↗