4

Upgrade Guide To Spring Boot 3.0 - DZone

 1 year ago
source link: https://dzone.com/articles/upgrade-guide-to-spring-boot-3-for-spring-data-jpa-3-and-querydsl-5
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Upgrade Guide To Spring Boot 3.0 for Spring Data JPA and Querydsl

Learn more about the adaptation to the latest Spring Boot 3.0.2 and Spring Data JPA 3.0.1.

by

CORE ·

Feb. 22, 23 · Tutorial
Like (1)
577 Views

Last year, I wrote two articles about JPA Criteria and Querydsl (see Introduction and Metamodel articles). Since the end of last year,  there's been a new major release of Spring Boot 3. This release is based on Spring Framework 6 with several significant changes and issues which we should consider when upgrading.

The goal of this article is to highlight these changes when upgrading the sat-jpa project (SAT project). The technologies used here are:

  1. Spring Boot 3.0.2,
  2. Hibernate 6.1.6.Final
  3. Spring Data JPA 3.0.1 and
  4. Querydsl 5.0.0.

Spring Framework 6.0.4

Spring Framework 6 has many changes (see What's New in Spring Framework 6.x), the key changes are:

  1. Switch Java baseline to Java 17 (still the last Java LTS at the time of writing this article) — i.e., it's a minimum Java version we have to use.
  2. Switch Jakarta baseline to Jakarta EE 9+.

Besides that, there's just one minor change in Spring MVC used in SAT project.

Spring MVC 6.0.4

All methods in the ResponseEntityExceptionHandler class changed their signatures. The status  argument was changed from HttpStatus to HttpStatusCode type (see the change in the CityExceptionHandler class).

HttpStatus in Spring MVC 5

@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException exception,
		HttpHeaders headers, HttpStatus status, WebRequest request) {
	return buildResponse(BAD_REQUEST, exception);
}

HttpStatusCode in 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 has many changes (see Spring Boot 3.0 Release Notes); the most important are these ones:

  • Java 17 (defined by the Spring Framework).
  • Bump up to Spring Framework 6 (see above).
  • Bump up to Hibernate 6 (see below).
  • Migration from JavaEE to Jakarta EE dependencies — it's not important in our case as we don't rely on enterprise Java here, but it can affect many dependencies (e.g., servlet API, validation,  persistence, JMS, etc.).
  • Minor change in Spring MVC 6 in the ResponseEntityExceptionHandler class (see the next part).

Let's start with the simple Jakarta EE changes. So we can focus on persistence after that.

Jakarta EE Dependencies

The significant change is the migration from Java EE to Jakarta EE dependencies. Spring Framework 6 set the baseline as Jakarta EE 9 (see What's New in Spring Framework 6.x), but Spring Boot 3 already uses Jakarta EE 10 (see Spring Boot 3.0 Release Notes ) for many APIs (e.g., Servlet or JPA — to name some technologies).

As a consequence, all classes using another class from the jakarta package has to switch to the same class from the javax package instead (see, e.g., PostConstruct or Entity annotations).

Javax Imports

import javax.annotation.PostConstruct;
import javax.persistence.Entity;

Jakarta Imports

import jakarta.annotation.PostConstruct;
import jakarta.persistence.Entity;

Hibernate 6.1.6

Another major change in Spring Boot 3 is the upgrade from Hibernate 5.6 to Hibernate 6.1. The details about Hibernate 6.1 can be found here or inside the release notes.

Honestly, I didn't pay attention to this change until I had to fix one failing test due to a different result size (see the fix in the CountryRepositoryCustomTests class). The implementation with the new Hibernate 6 returns fewer entities than before.

It's worth mentioning two changes here based on this investigation. Let's start with logging first.

Logging

The Hibernate loggers were changed from org.hibernate.type to org.hibernate.orm.jdbc (see this reference and this reference).

Note: all available configuration items can be found in org.hibernate.cfg.AvailableSettings class.

Hibernate 5

There was a single logger for the bidden and extracted values.

Properties files
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

Hibernate 6

Hibernate 6 changed the main package and split them into two different loggers in order to distinguish the operation -> what value should be logged.

Properties files
logging.level.org.hibernate.orm.jdbc.bind=trace
logging.level.org.hibernate.orm.jdbc.extract=trace

Semantic Query Model

As the logging was fixed, it was confirmed that the Hibernate really extracts two records from DB:

Plain Text
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]

However, the test receives only a single entity from the Hibernate, as you can see in these debugging screenshots:

Debugging Screenshot

The changed behavior is caused by the new Semantic Query Model with Automatic deduplication (see Semantic Query Model part) introduced with the Hibernate 6 (see line 178 in org.hibernate.sql.results.spi.ListResultsConsumer class). The Hibernate 6 returns the deduplicated result now.

Hibernate JPA Generator

The Hibernate Jpamodelgen maven dependency managed by Spring Boot Dependencies was moved from org.hibernate to org.hibernate.orm package. See:

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

To finish the core persistence dependencies, the Liquibase is upgraded from version 4.9.1 to 4.17.2. There's no significant difference except the JAX-B dependency usage. The dependency should use JAX-B from Jakarta instead of Javax (see the following reference).

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

The Spring Boot 3.0.2 depends on Spring Data Release Train 2022.0.1 (see Spring Data 2022.0 - Turing Release Notes), where Spring Data JPA 3.0.1 is used with these key changes (see the release notes):

  1. Switch Java baseline to Java 17,
  2. Switch Jakarta baseline to Jakarta EE 10 and
  3. Bump up to Hibernate 6

Note: the previously used version (in our case) was the 2.7.5 version.

Querydsl 5.0.0

The Querydsl version was not changed, but it was impacted in a similar way as the Liquibase. The dependencies have to be used from Jakarta instead of Javax. Therefore, the Querydsl dependency has to use jakarta classifier instead of the old jpa classifier (see this reference).

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>

Conclusion

This article has covered the upgrade to the latest Spring Boot 3.0.2 for JPA and Querydsl (at the time of writing this article). The article started with Spring Framework, and Spring Boot changes. Next, all changes to Hibernate and related technologies were covered.  In the end, we mentioned the minor changes related to Spring Data 3.0.1 and Querydsl 5.0.0.

The complete source code demonstrated above is available in my GitHub repository.

Note: there is also a preceding article, Upgrade Guide To Spring Data Elasticsearch 5.0, dedicated to a similar upgrade of Elasticsearch with Spring Boot 3.


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK