-
Notifications
You must be signed in to change notification settings - Fork 699
Spring Data 2025.1 Release Notes
-
Upgrade to Spring Framework 7
-
Upgrade to Jakarta EE 11 (JPA 3.2, Servlet 6.1)
-
Upgrade to Kotlin 2.1
-
Strong use of JPQL in JPA
-
Removal of
ListenableFuturesupport
Details
-
Spring Data Build - 4.0
With Spring Framework removing support for ListenableFuture, we’re removing support for ListenableFuture as well. Please use CompletableFuture when using @Async query methods.
PersistenceConstructor Migration
-
Removal of
@PersistenceConstructorin favor of@PersistenceCreator -
Removal of
Parameter.hasSpelExpression()in favor ofhasValueExpression(). -
Removal of
PersistentEntity.getPersistenceConstructor()in favor ofPersistentEntity.getInstanceCreatorMetadata()andisConstructorArgument(…)in favor ofisCreatorArgument(…). -
Removal of
PreferredConstructor.isConstructorParameter(…)isCreatorParameter(…). -
Removal of
MappingInstantiationException.getConstructor(…)in favor ofgetEntityCreator().
SpEL to Value Expression Migration
-
Removal of
DefaultSpELExpressionEvaluatorandSpELExpressionEvaluatorin favor ofValueExpressionEvaluator. -
Removal of
SpELExpressionParameterValueProviderin favor ofValueExpressionParameterValueProvider. -
Removal of
ValueExpressionParameterValueProvider.potentiallyConvertSpelValue(…)in favor ofpotentiallyConvertExpressionValue(…). -
Removed
ExtensionAwareQueryMethodEvaluationContextProvider,QueryMethodEvaluationContextProviderand their reactive variants in favor of Value Expression support.QueryMethodValueEvaluationContextAccessor.createEvaluationContextProvider(beanFactory)can help to create default instances. -
Removed
SpelEvaluatorandSpelQueryContextin favor ofValueExpressionQueryRewriter
QueryMethod Parameters Revision
-
Removed
QueryMethod.createParameters(Method method, TypeInformation<?> domainType)in favor ofcreateParameters(ParametersSource parametersSource) -
Removal of
Parameter(MethodParameter parameter)andParameters(Method method, Function<MethodParameter, T> parameterFactory).
ClassUtils and ReflectionUtils Revision
-
Removal of
CastUtilswithout replacement. Apply casting where necessary. -
Removal of
org.springframework.data.repository.util.ClassUtils. Several methods went intoorg.springframework.data.util.ClassUtilsandReflectionUtils.
Begin the process of stopping support for proxying web handler method params that are not explicitly annotated with @ProjectedPayload (either at the type or parameter level) by logging a warning for each qualifying parameter that this style is deprecated and that we will drop support for this a future release.
Other Changes
-
Removal of
PersistentPropertyPath.getRequiredLeafProperty()in favor ofgetLeafProperty(). -
QPageRequestconstructors areprivatenow, useoffactory methods. -
Removal of
AnnotationRepositoryConfigurationSourceconstructor -
Removal of
RepositoryFactorySupport.getTargetRepositoryViaReflection(…), useinstantiateClass(…)instead. -
Removed
PagedResourcesAssembler.getMethodParameter(…)without replacement -
Removed
org.springframework.data.repository.util.ReactiveWrappersin favor of the variant in theorg.springframework.data.utilpackage. -
ClassTypeInformationwas made package-protected. Obtain instances ofTypeInformationusing the appropriate factory methods onTypeInformation. -
Removal of the
org.springframework.data.type.classreadingpackage in favor of Spring’sAnnotationMetadata.
Spring Data JPA 4.0 upgrades its baseline to JPA 3.2, requiring Hibernate 7.0 and respective Eclipselink 5.0 runtime versions. With the upgrade, we refined our implementations to use Query.getSingleResultOrNull() for single-result query methods, resulting in the avoidance of NoResultException. Further changes include support of union, intersect, except, cast, left, right, and replace functions, and support for the || string concatenation operator.
Upgrading to JPA 3.2 allows consistent support for nulls precedence in Sort expressions as the Criteria Query API allows declaration of nulls precedence. Previously, we only supported nulls precedence in JPQL queries.
15 years ago, Spring Data JPA started to see first light. Back then, it used String-based queries and eventually moved to JPA’s CriteriaQuery API to avoid string concatenation when building queries. It has been quite a ride with the Criteria API being powerful yet restricted as Hibernate was capable of way more functionality than exposed through the Criteria API (e.g. Nulls Precedence when sorting).
A couple of years into Criteria API, we started noticing a huge performance penalty using Criteria API. JPA providers have to evaluate the entire query on each query creation, whereas Hibernate is able to cache queries much better when using String-based JPQL queries.
We finally decided to explore a JPQL-based approach to derived queries and we found a 3.5x improvement in running such queries. While the factor 3.5x applies to in-memory databases, a typical application can still benefit from a roughly 25% improvement in query throughput by leveraging Hibernate’s query caching.
Using a different API that has proven over 15 years bears quite some risk in breaking applications that otherwise ran fine. We would appreciate your feedback on cases that behave differently than the previous version.
We revised our Specification API to reflect its usage better. Over time, we introduced specification support for delete queries, which uses a different query type hierarchy (CriteriaDelete), and that wasn’t an ideal fit for existing interfaces accepting CriteriaQuery.
We introduced DeleteSpecification and UpdateSpecification to enable seamless usage of delete respective update queries. Along with that change, we also introduced PredicateSpecification to define reusable specification functions that return Predicate regardless of the query context in which they are used.
Related to a refined Specification API, we extended the fluent findBy(…) API to return a Slice without running a count query. Also, paginated queries optionally accept a count specification if the count query should be provided (i.e., an optimized query).
A selected set of expressions can now be used with JpaSort.unsafe(…) together with Specifications. The newly introduced parser for ORDER BY expressions translates ORDER BY items to JPA’s Criteria API Expressions as much as possible. ORDER BY parsing can translate simple path expressions, function calls, and CASE clauses. Any more complex ordering items should be provided directly to CriteriaQuery.
With this release, we widely revised DeclaredQuery and QueryEnhancer. Since introducing JSqlParser with Spring Data 3.0, we have constantly extended capabilities to introspect and rewrite queries. At some point, we were asked to force JSqlParser (or disable JSqlParser usage) but that turned out to be impossible given its design. We had to revise our arrangement entirely to decouple the individual parsing and analysis stages a declared query goes through.
Additionally, parts of DeclaredQuery and QueryEnhancer have been public API without intending to do so. With this major revision, we decoupled DeclaredQuery from its sole StringQuery implementation that would parse and introspect queries without a way to provide a strategy to select the intended QueryEnhancer.
QueryEnhancer is now slimmed down to essential methods that are necessary for Query Introspection and Rewriting. QueryEnhancerSelector allows the implementation of QueryEnhancer selection (Regex, JSqlParser, JPQL). You can even provide your own QueryEnhancer implementation.
With that change, the spring.data.jpa.query.native.parser option is gone and no longer available. You can configure QueryEnhancerSelector through @EnableJpaRepositories:
@Configuration
@EnableJpaRepositories(queryEnhancerSelector = MyQueryEnhancerSelector.class)
class ApplicationConfig {
// …
}JMX support has been deprecated in version 4.5 and removed in 5.0. We recommend switching to Spring Boot Actuator Endpoints and exposing those over JMX if needed.
The newly introduced QueryResultConverter allows to contextually post-process results, providing access to both the raw Document as well as the already mapped object, which can be useful when there is a need to apply additional transformations.
List<Optional<Jedi>> result = template.query(Person.class)
.as(Jedi.class)
.matching(query(where("firstname").is("luke")))
.map((document, reader) -> Optional.of(reader.get()))
.all();With Spring Framework removing support for ListenableFuture, we’re removing support for ListenableFuture as well. Packages org.springframework.data.cassandra.core.cql.legacy and o.s.d.c.core.legacy are removed. Use asynchronous template API implementations and their utilities from o.s.d.c.core.cql respective o.s.d.c.core returning CompletableFuture.
The new QueryResultConverter is useful when there is a need to apply additional contextual transformations as it provides access to both the Row as well as the already mapped object as outlined below.
List<Optional<Jedi>> results = template.query(Person.class)
.as(Jedi.class)
.map((row, reader) -> Optional.of(reader.get())
.all();-
M1 - January 2025
-
M2 - April 2025
-
M3 - May 2025
-
M4 - July 2025
-
RC1 - Sept 2025
-
RC2 - Oct 2025
-
GA - Nov 2025
-
OSS Support until: May 2025
-
End of Life: Sept 2026