[#2845] Bump Spring boot to 4.x (#2941)

Notes:
1. (!) Eclipselink shall be migrated to 5.0 (in 4.0.8 there are incompatible classes, e.g EJBQueryImpl doesn't implement some newer methods). In the moment is with beta (5.0.0-B12) - JUST for testing!
2. (!) Ethlo plugin doesn't work with Eclipselink 5.0, it builds with Eclipselink 4.0.8 (could be a problem)
3. Dependencies - new starters, test starters changes, some dependencies refactoring
4. Auto-configs split - package changes, some properties classes changes
5. Spring nullable org.springframework.lang.Nullable/NonNull are depecated and replaced with jspcify -> org.jspecify.annotations.Nullable/NonNull (NullMarked)
6. Lombok config - adding lombok.addNullAnnotations=jspecify - to do not mess annotations
7. Distributed lock table changes - SP_LOCK table db migration
8. Spring Retry replaced with Spring Core Retry - does repace retry in hawkbit
9. Specifications -> added Update/Delete(/Predicate) Specifications and JpaSpecificationExecutor changed
10. HawkbitBaseRepositoryFactoryBean modified to register properly
11. Jackson - 2 -> 3, package migrations, finals are not deserialized by default(enable finals deserialization, consider make non-final), too ‘smart’ tries to set complex objects instead of using non args constructor (-> @JsonIgnore), some other default configs made

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2026-04-14 11:31:41 +03:00
committed by GitHub
parent 23cd368e00
commit 1be473b22c
172 changed files with 1254 additions and 1045 deletions

View File

@@ -22,6 +22,11 @@
<name>hawkBit :: Query Language :: JPA</name>
<dependencies>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
@@ -34,19 +39,9 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
</exclusion>
</exclusions>
<optional>true</optional>
</dependency>
@@ -56,6 +51,11 @@
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>

View File

@@ -22,8 +22,10 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.query.sqm.internal.QuerySqmImpl;
import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.internal.SqmQueryImpl;
import org.hibernate.query.sqm.internal.SqmUtil;
import org.hibernate.query.sqm.spi.SqmParameterMappingModelResolutionAccess;
import org.hibernate.query.sqm.sql.SqmTranslation;
@@ -33,6 +35,7 @@ import org.hibernate.query.sqm.tree.SqmDmlStatement;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.tree.MutationStatement;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.ast.tree.select.SelectStatement;
@@ -60,14 +63,14 @@ public class HibernateUtils {
throw new UnsupportedOperationException("SqmTranslatorFactory resolver is not available");
}
final QuerySqmImpl<?> hqlQuery = query.unwrap(QuerySqmImpl.class);
final SessionFactoryImplementor factory = hqlQuery.getSessionFactory();
final SqmQueryImpl<?> hqlQuery = query.unwrap(SqmQueryImpl.class);
final SessionFactoryImplementor sessionFactory = hqlQuery.getSessionFactory();
final SharedSessionContractImplementor session = hqlQuery.getSession();
final SessionFactoryImplementor sessionFactory = session.getFactory();
final SqlAstCreationContext sqlAstCreationContext = (SqlAstCreationContext)session.getFactory();
final SqmTranslatorFactory sqmTranslatorFactory;
try {
sqmTranslatorFactory = (SqmTranslatorFactory) getSqmTranslatorFactory.invoke(factory.getQueryEngine());
sqmTranslatorFactory = (SqmTranslatorFactory) getSqmTranslatorFactory.invoke(sessionFactory.getQueryEngine());
} catch (final IllegalAccessException | InvocationTargetException e) {
throw new UnsupportedOperationException("Can't create SqmTranslatorFactory", e);
}
@@ -76,19 +79,20 @@ public class HibernateUtils {
hqlQuery.getSqmStatement() instanceof SqmSelectStatement<?> selectStatement
? sqmTranslatorFactory.createSelectTranslator(selectStatement,
hqlQuery.getQueryOptions(), hqlQuery.getDomainParameterXref(), hqlQuery.getQueryParameterBindings(),
hqlQuery.getLoadQueryInfluencers(), sessionFactory, false)
hqlQuery.getLoadQueryInfluencers(), sqlAstCreationContext, false)
: sqmTranslatorFactory.createMutationTranslator((SqmDmlStatement<?>) hqlQuery.getSqmStatement(),
hqlQuery.getQueryOptions(), hqlQuery.getDomainParameterXref(), hqlQuery.getQueryParameterBindings(),
hqlQuery.getLoadQueryInfluencers(), sessionFactory);
hqlQuery.getLoadQueryInfluencers(), sqlAstCreationContext);
final SqmTranslation<? extends Statement> sqmTranslation = sqmSelectTranslator.translate();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = factory.getJdbcServices().getJdbcEnvironment().getSqlAstTranslatorFactory();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = sessionFactory.getJdbcServices().getJdbcEnvironment().getSqlAstTranslatorFactory();
final Map<QueryParameterImplementor<?>, Map<SqmParameter<?>, List<JdbcParametersList>>> jdbcParamsXref = SqmUtil.generateJdbcParamsXref(
hqlQuery.getDomainParameterXref(), sqmTranslation::getJdbcParamsBySqmParam);
final JdbcParameterBindings jdbcParameterBindings = SqmUtil.createJdbcParameterBindings(hqlQuery.getQueryParameterBindings(),
hqlQuery.getDomainParameterXref(), jdbcParamsXref, factory.getRuntimeMetamodels().getMappingMetamodel(),
sqmSelectTranslator.getFromClauseAccess()::findTableGroup, new SqmParameterMappingModelResolutionAccess() {
final JdbcParameterBindings jdbcParameterBindings = SqmUtil.createJdbcParameterBindings(
(QueryParameterBindings) hqlQuery.getQueryParameterBindings(),
(DomainParameterXref) hqlQuery.getDomainParameterXref(), jdbcParamsXref, /*sessionFactory.getRuntimeMetamodels().getMappingMetamodel(),
sqmSelectTranslator.getFromClauseAccess()::findTableGroup,*/ new SqmParameterMappingModelResolutionAccess() {
@Override
@SuppressWarnings("unchecked")
@@ -97,9 +101,9 @@ public class HibernateUtils {
}
}, hqlQuery.getSession());
return (sqmTranslation.getSqlAst() instanceof SelectStatement selectStatement
? sqlAstTranslatorFactory.buildSelectTranslator(factory, selectStatement)
? sqlAstTranslatorFactory.buildSelectTranslator(sessionFactory, selectStatement)
.translate(jdbcParameterBindings, hqlQuery.getQueryOptions())
: sqlAstTranslatorFactory.buildMutationTranslator(factory, (MutationStatement) sqmTranslation.getSqlAst())
: sqlAstTranslatorFactory.buildMutationTranslator(sessionFactory, (MutationStatement) sqmTranslation.getSqlAst())
.translate(jdbcParameterBindings, hqlQuery.getQueryOptions()))
.getSqlString();
}

View File

@@ -26,12 +26,11 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
import org.springframework.data.jpa.domain.Specification;
@SuppressWarnings("java:S5961") // complex check because the matter is very complex
@DataJpaTest(properties = { "spring.jpa.database=H2" }, excludeAutoConfiguration = { FlywayAutoConfiguration.class })
@DataJpaTest(properties = "spring.jpa.database=H2")
@EnableAutoConfiguration
@Slf4j
class SpecificationBuilderTest {