QueryDSL mit Spring Boot 3 nutzen
Auf Arbeit sind wir gerade dabei, sämtliche Anwendungen auf Spring Boot 3 zu aktualisieren. Die meisten Anpassungen dafür sind trivial, QueryDSL hat mir aber etwas Kopfzerbrechen bereitet, da die Dokumentation noch auf einem alten Stand ist.
Konfiguration vor Spring Boot 3
Bislang wurde QueryDSL wie folgt eingebunden:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.7</version>
</parent>
<groupId>example</groupId>
<artifactId>example</artifactId>
<version>0.0.0-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
<outputDirectory>target/generated-sources/java</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
</dependencies>
</project>
Update auf Spring Boot 3
Die Umstellung auf Spring Boot 3 erfolgt durch Anpassung des Elternprojektes:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
</parent>
Hibernate 6 / Jakarta EE Kompatibilität
Da Spring Boot 3 nun jedoch Hibernate 6 verwendet, das wiederum auf Jakarta EE basiert, werden mit dieser Konfiguration inkompatible Q-Klassen erstellt (siehe Support Hibernate 6.x.x #3436). Das lässt sich schnell beheben, indem spezielle Jakarta-Pakete verwendet werden. Durch die Umstellung muss auch explizit die Versionsnummer bei den Paketen mit angegeben werden:
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<classifier>jakarta</classifier>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
<classifier>jakarta</classifier>
</dependency>
</dependencies>
Fehler beim Erzeugen der Q-Klassen
Nach dieser Anpassung werden die Q-Klassen aber sowohl unter target/generated-sources/java als auch unter target/generated-sources/annotations erzeugt.
Schuld daran ist eine Service Deklaration, die zwar in den Jakarta-Paketen nicht jedoch in den Standard-Paketen enthalten ist (siehe JPAAnnotationProcessor with classifier jakarta fails with "Attempt to recreate a file for type" #3431). Das Problem kann ganz einfach gelöst werden, indem das nun überflüssige apt-maven-plugin entfernt wird.
Komplette Konfiguration
Die Komplette QueryDSL-Konfiguration für Spring Boot 3 sieht nun wie folgt aus:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
</parent>
<groupId>example</groupId>
<artifactId>example</artifactId>
<version>0.0.0-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<classifier>jakarta</classifier>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
<classifier>jakarta</classifier>
</dependency>
</dependencies>
</project>