Spring Boot 3 y Querydsl: configurar Jakarta y generar tipos Q
En esta página
Para generar tipos Q de Querydsl JPA en Spring Boot 3, alinea las versiones y clasificadores jakarta de querydsl-jpa y querydsl-apt, configura el procesamiento de anotaciones y comprueba una compilación limpia y una prueba de consulta. Las notas de Querydsl 5.0 documentan el clasificador Jakarta. Mantener las rutas predeterminadas de Gradle evita que la compilación principal y de pruebas escriban en el mismo directorio.
Esta guía desarrolla el ejemplo coreano original de 2023 hasta una configuración ejecutable. Las versiones fijan el entorno de reproducción; no recomiendan dependencias actuales para producción.
Flujo de procesamiento
El procesador genera QEmployee durante la compilación principal. Después la prueba H2 ejecuta una consulta con esos tipos generados.
Entorno de reproducción y configuración Gradle completa
| Componente | Versión de reproducción |
|---|---|
| JDK / Gradle | 17.0.8.1 / 8.4 |
| Spring Boot BOM | 3.5.7 |
| Querydsl JPA / APT | 5.1.0, ambos con clasificador jakarta |
| Hibernate / H2 | 6.6.33.Final / 2.3.232, gestionados por el BOM |
Crea estos cinco archivos en un directorio nuevo. El proyecto de pruebas usa el plugin Java y el BOM de Boot; no necesita el plugin Gradle de Boot. En una aplicación Boot existente, añade solo las dependencias necesarias junto a la gestión de dependencias elegida.
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 resuelve annotationProcessor aparte de los classpath normales de compilación y ejecución. Por ello el ejemplo aplica el BOM también a la configuración del procesador y aporta explícitamente las API Jakarta Persistence y Annotation. Una dependencia implementation no está disponible automáticamente para el procesador. Consulta la documentación del plugin Java de Gradle.
Crear la aplicación y la entidad
La clase de aplicación permite a la prueba JPA descubrir la configuración de Boot. No hace falta arrancar un proceso de servidor separado para la prueba.
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 usa jakarta.persistence. No escribas QEmployee manualmente: el procesador de anotaciones genera el tipo al que se refiere la prueba siguiente.
Consultar mediante el tipo Q generado
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 usa H2 del classpath del ejemplo. Cada prueba se ejecuta en una transacción y revierte después. Tras insertar datos con persistAndFlush, el QEmployee generado permite dos comprobaciones: coincidencia exacta de nombre y consulta sin filas. Consulta la guía de pruebas JPA de Spring Boot.
Estas pruebas comprueban esta entidad y consulta en H2. No verifican el dialecto SQL, cotejamiento, bloqueo ni comportamiento de migraciones de tu base de producción.
Ejecutar e inspeccionar los archivos generados
Selecciona JDK 17 y usa Gradle 8.4 instalado. Ejecuta desde la raíz del proyecto:
java -version
gradle --version
gradle --no-daemon clean test
Comprueba estos artefactos generados y el informe de pruebas:
build/generated/sources/annotationProcessor/java/main/example/QEmployee.java
build/classes/java/main/example/QEmployee.class
build/reports/tests/test/index.html
Ambas pruebas pasaron con esta configuración. Repetir clean test regeneró el tipo Q y volvió a pasar ambas pruebas. En un proyecto existente con Gradle wrapper, usa su versión elegida mediante ./gradlew clean test.
El tipo Q generado importa javax.annotation.processing.Generated, una API Java SE de java.compiler. Ese import no necesita reemplazo Jakarta. API Generated de JDK 17.
¿Por qué faltan los tipos Q o se generan dos veces?
| Síntoma | Primera comprobación |
|---|---|
No se encuentra QEmployee |
Comprueba el resultado CLI clean compileJava, las dependencias del procesador y los imports jakarta.persistence de la entidad. |
| El procesador no encuentra las API Persistence | Comprueba que las API Jakarta necesarias estén en la ruta del procesador, aparte del classpath normal. |
Aparece un tipo javax.persistence.EntityManager incompatible |
Comprueba versiones coincidentes y clasificadores Jakarta para ambos artefactos Querydsl. |
| Tipos Q duplicados o compilación que solo funciona tras clean | Elimina fuentes Q manuales y rutas generadas compartidas; inspecciona la salida main/test. |
| CLI pasa pero el IDE no ve los tipos Q | Comprueba sincronización Gradle, compilación delegada y procesamiento de anotaciones del IDE. |
El ejemplo no añade configuración personalizada de sourceSets, JavaCompile ni clean para archivos generados. Si necesitas una ruta propia, separa las salidas main y test. configureEach controla la configuración diferida de tareas; no corrige la compatibilidad Jakarta. Evitación de configuración de Gradle.
Para la secuencia de actualización, consulta la guía de migración a Spring Boot 3. Para límites HTTP salientes, usa las pruebas WebClient y MockWebServer.
Comparar antes de cambiar de herramienta de consultas
La clase Employee completa incluye un getter para comparar los resultados como nombres. Añade los tres archivos de la comparación Querydsl y Specification para ejecutar ocho comprobaciones adicionales sobre la misma entidad. Las dos pruebas originales siguen formando parte de ese proyecto de diez pruebas. Compara predicados H2 seleccionados, no todo el comportamiento de la base. La guía Spring Boot conecta los pasos de preparación y pruebas relacionados.
Comentarios