El año pasado, escribí dos artículos sobre JPA Criteria y Querydsl (consulte los artículos Introducción y Metamodel). Desde fines del año pasado, ha habido un nuevo lanzamiento importante de Spring Boot 3. Este lanzamiento se basa en Spring Framework 6 con varios cambios significativos y problemas que debemos considerar al actualizar.
El objetivo de este artículo es resaltar estos cambios al actualizar el proyecto sat-jpa (proyecto SAT). Las tecnologías utilizadas aquí son:
- Spring Boot 3.0.2,
- Hibernate 6.1.6.Final
- Spring Data JPA 3.0.1 y
- Querydsl 5.0.0.
Spring Framework 6.0.4
Spring Framework 6 tiene muchos cambios (consulte ¿Qué hay de nuevo en Spring Framework 6.x?), los cambios clave son:
- Cambiar la línea de base de Java a Java 17 (aún la última versión LTS de Java en el momento de escribir este artículo) — es decir, es la versión mínima de Java que debemos usar.
- Cambiar la línea de base de Jakarta a Jakarta EE 9+.
Además de eso, solo hay un cambio menor en Spring MVC utilizado en el proyecto SAT.
Spring MVC 6.0.4
Todos los métodos en la clase ResponseEntityExceptionHandler
cambiaron sus firmas. El argumento status
se cambió de tipo HttpStatus
a HttpStatusCode
(ver el cambio en la clase CityExceptionHandler).
HttpStatus en Spring MVC 5
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException exception,
HttpHeaders headers, HttpStatus status, WebRequest request) {
return buildResponse(BAD_REQUEST, exception);
}
HttpStatusCode en Spring MVC 6
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException exception,
HttpHeaders headers, HttpStatusCode status, WebRequest request) {
return buildResponse(BAD_REQUEST, exception);
}
Spring Boot 3.0.2
Spring Boot 3 tiene muchos cambios (ver Notas de lanzamiento de Spring Boot 3.0); los más importantes son estos:
- Java 17 (definido por el Framework Spring).
-
Actualización al Framework Spring 6 (ver arriba).
-
Actualizar a Hibernate 6 (ver abajo).
- Migración de dependencias de JavaEE a Jakarta EE — no es importante en nuestro caso ya que no dependemos de Java empresarial, pero puede afectar a muchas dependencias (por ejemplo, API de servlet, validación, persistencia, JMS, etc.).
- Modificación menor en Spring MVC 6 en la clase
ResponseEntityExceptionHandler
(ver la siguiente parte).
Comencemos con los cambios simples de Jakarta EE. Así podemos centrarnos en la persistencia después de eso.
Dependencias de Jakarta EE
El cambio significativo es la migración de dependencias de Java EE a Jakarta EE. Spring Framework 6 estableció la base como Jakarta EE 9 (ver Qué hay de nuevo en Spring Framework 6.x), pero Spring Boot 3 ya utiliza Jakarta EE 10 (ver Notas de lanzamiento de Spring Boot 3.0) para muchas API (por ejemplo, Servlet o JPA — para mencionar algunas tecnologías).
Como consecuencia, todas las clases que utilizan otra clase del paquete jakarta
deben cambiar a la misma clase del paquete javax
en su lugar (ver, por ejemplo, anotaciones PostConstruct o Entity).
Importaciones Javax
import javax.annotation.PostConstruct;
import javax.persistence.Entity;
Importaciones Jakarta
import jakarta.annotation.PostConstruct;
import jakarta.persistence.Entity;
Hibernate 6.1.6
Otro cambio importante en Spring Boot 3 es la actualización de Hibernate 5.6 a Hibernate 6.1. Los detalles sobre Hibernate 6.1 se pueden encontrar aquí o dentro de las notas de lanzamiento.
Sinceramente, no preste atención a este cambio hasta que tuve que corregir una prueba fallida debido a un tamaño de resultado diferente (ver el arreglo en la clase CountryRepositoryCustomTests
). La implementación con el nuevo Hibernate 6 devuelve menos entidades que antes.
Vale la pena mencionar dos cambios aquí basados en esta investigación. Comencemos primero con el registro.
Registro
Los registradores de Hibernate se cambiaron de org.hibernate.type
a org.hibernate.orm.jdbc
(consulte esta referencia y esta referencia).
Nota: todos los elementos de configuración disponibles se pueden encontrar en la clase org.hibernate.cfg.AvailableSettings
.
Hibernate 5
Había un solo registrador para los valores marcados y extraídos.
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
Hibernate 6
Hibernate 6 cambió el paquete principal y los dividió en dos registradores diferentes para distinguir la operación -> qué valor debe registrarse.
logging.level.org.hibernate.orm.jdbc.bind=trace
logging.level.org.hibernate.orm.jdbc.extract=trace
Modelo de Consulta Semántico
Una vez solucionado el registro, se confirmó que Hibernate realmente extrae dos registros de la BD:
2023-01-25T08:40:18.819+01:00 INFO 6192 --- [ main] c.g.a.s.j.c.CountryRepositoryCustomTests : Started CountryRepositoryCustomTests in 4.678 seconds (process running for 5.745)
Hibernate: select c2_0.id,c2_0.name from city c1_0 join country c2_0 on c2_0.id=c1_0.country_id where c1_0.name like ? escape '!' and c1_0.state like ? escape '!'
2023-01-25T08:40:19.221+01:00 TRACE 6192 --- [ main] org.hibernate.orm.jdbc.extract : extracted value ([1] : [BIGINT]) - [3]
2023-01-25T08:40:19.222+01:00 TRACE 6192 --- [ main] org.hibernate.orm.jdbc.extract : extracted value ([2] : [VARCHAR]) - [USA]
2023-01-25T08:40:19.240+01:00 TRACE 6192 --- [ main] org.hibernate.orm.jdbc.extract : extracted value ([1] : [BIGINT]) - [3]
2023-01-25T08:40:19.241+01:00 TRACE 6192 --- [ main] org.hibernate.orm.jdbc.extract : extracted value ([2] : [VARCHAR]) - [USA]
Sin embargo, la prueba recibe solo una entidad de Hibernate, como se puede ver en estas capturas de pantalla de depuración:
El comportamiento cambiado se debe al nuevo Modelo de Consulta Semántico con eliminación automática de duplicados (consulte la parte Modelo de Consulta Semántico) introducido con Hibernate 6 (consulte la línea 178 en la clase org.hibernate.sql.results.spi.ListResultsConsumer
). Ahora Hibernate 6 devuelve el resultado deduplicado.
Generador JPA de Hibernate
La dependencia de Maven Hibernate Jpamodelgen gestionada por Spring Boot Dependencies fue trasladada del paquete org.hibernate
al paquete org.hibernate.orm
. Consulte:
Spring Boot 2.7.5
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
</dependency>
Spring Boot 3.0.2
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
</dependency>
Liquibase
Para completar las dependencias de persistencia central, Liquibase fue actualizado de la versión 4.9.1 a 4.17.2. No hay diferencias significativas excepto en el uso de la dependencia JAX-B. La dependencia debe utilizar JAX-B de Jakarta en lugar de Javax (consulte el siguiente referencia).
Spring Boot 2.7.5
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
Spring Boot 3.0.2
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<exclusions>
<exclusion> <!-- due to SB 3.0 switch to Jakarta -->
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
Spring Data JPA 3.0.1
Spring Boot 3.0.2 depende de Spring Data Release Train 2022.0.1 (consulte Spring Data 2022.0 – Notas de lanzamiento de Turing), donde Spring Data JPA 3.0.1 se utiliza con estos cambios clave (consulte las notas de lanzamiento):
- Cambio de la base de Java a Java 17,
- Cambio de la base de Jakarta a Jakarta EE 10 y
- Aumentar a Hibernate 6
Nota: la versión utilizada anteriormente (en nuestro caso) era la 2.7.5.
Querydsl 5.0.0
La versión de Querydsl no se cambió, pero se vio afectada de manera similar a Liquibase. Las dependencias deben utilizarse de Jakarta en lugar de Javax. Por lo tanto, la dependencia de Querydsl debe usar el clasificador jakarta
en lugar del antiguo clasificador jpa
(ver este referencia).
Spring Boot 2.7.5
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<classifier>jpa</classifier>
<scope>provided</scope>
</dependency>
Spring Boot 3.0.2
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
<classifier>jakarta</classifier>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<scope>provided</scope>
<version>${querydsl.version}</version>
<classifier>jakarta</classifier>
</dependency>
Conclusión
Este artículo ha cubierto la actualización a la última versión de Spring Boot 3.0.2 para JPA y Querydsl (en el momento de escribir este artículo). El artículo comenzó con los cambios en Spring Framework y Spring Boot. A continuación, se cubrieron todos los cambios en Hibernate y tecnologías relacionadas. Al final, mencionamos los cambios menores relacionados con Spring Data 3.0.1 y Querydsl 5.0.0.
El código fuente completo demostrado anteriormente está disponible en mi GitHub repositorio.
Nota: también hay un artículo anterior, Guía de actualización para Spring Data Elasticsearch 5.0, dedicado a una actualización similar de Elasticsearch con Spring Boot 3.
Source:
https://dzone.com/articles/upgrade-guide-to-spring-boot-3-for-spring-data-jpa-3-and-querydsl-5