-
Notifications
You must be signed in to change notification settings - Fork 674
Spring Data 2021.2 (Raj) Release Notes
-
Direct projections
-
Property-specific converters
Details
-
Spring Data Build - 2.7
SimpleTypeInformationMapper
now accepts a ClassLoader
to ensure class visibility from the type mapper when resolving a class name into a class. Arrangements without a configured class loader fall back to the context or system class loader which might not have access to a custom class loader (such as Spring Boot’s AppClassLoader) and that can lead to non-resolvable type hints when reading an entity on e.g. the ForkJoinPool
.
EntityProjection
provides an API to introspect projection types in the context of an entity to determine which property paths to consider during loading.
Property-based converters allow to specify conversion instructions on a per property basis either declarative, via @ValueConverter
, or programmatically by registering a PropertyValueConverter
for a specific field.
public class Person {
// ...
@ValueConverter(EncryptingValueConverter.class)
String ssn;
}
In case a derived query uses a DTO, we now create a select clause that uses a constructor expression for the DTO type. This wasn’t supported before and expected either an interface-based projection or an explicit query using a constructor expression.
We introduced JpaRepository.getReferenceById
as a replacement for JpaRepository.getById
, which should make the difference to JpaRepository.findById
more obvious.
Entity classes with an IdClass
for primary key caused problems with the latest Hibernate versions and also did not work with deleteAllByIdInBatch
. Both issues are now fixed.
You can now check for the existence of entities specified by a Specification
using JpaSpecificationExecutor.exists
.
When you use an ignoreCase
operator, whether that’s with standard finders, JSqlParser, Querydsl, or Query by Example, all will lower
the selected column, so you only need to maintain one index. If you currently have an index built for upper
, you can either remove it or replace it with a proper one.
The projection support through MongoTemplate
and its reactive variant are refined supporting nested projections directly on the converter-level allowing to avoid superfluous and partial entity creation as interface projections are backed by a map. DTO projections are read directly into the DTO type.
Modifying documents is supported via the @Update
annotation that, when added to a repository finder method, will run the defined expression against all matching documents, returning the number of updated ones.
@Update("{ '$inc' : { 'visits' : ?1 } }")
long findAndIncrementVisitsByLastname(String lastname, int increment);
@Update(pipeline = {"{ '$set' : { 'visits' : { '$add' : [ '$visits', ?1 ] } } }"})
long findAndIncrementVisitsViaPipelineByLastname(String lastname, int increment);
@Query("{ 'lastname' : ?0 }")
@Update("{ '$inc' : { 'visits' : ?1 } }")
long updateAllByLastname(String lastname, int increment);
The MongoDB Data module leverages the commons infrastructure to provide a store specific value conversion implementation via MongoValueConverter
and the MongoConversionContext
.
Next to the declarative approach using @ValueConverter
, MongoCustomConversions
allows programmatic registration of converter implementations that are only applied to defined properties.
MongoCustomConversions.create(it -> {
it.configurePropertyConversions(registrar -> {
registrar.registerConverter(Person.class, "ssn", new MongoValueConverter<>() { ... });
})
})
M1
-
#1995 - RestStatusException detail in v4.3.0.
-
#1997 - IndexOutOfBoundsException when try to map inner hits with no results returned.
-
#2015 - Totalhits support for ReactiveSearchOperations.
-
#2000 - Migrate off SLF4J to Spring JCL.
-
#2004 - Add support for stored fields.
-
#2020 - Upgrade to Elasticsearch 7.16.0.
-
#2024 - Fix mapping of FieldType.TokenCount.
-
#2030 - Upgrade to Elasticsearch 7.16.1.
-
#2034 - Upgrade to Elasticsearch 7.16.2.
-
#2009 - Add AfterLoad callback.
-
#1529 - Implement support for reindex API.
-
#2075 - RequestFactory.toElasticsearchIndicesOptions fails on empty options or wildcard states.
M2
-
#2059 - Upgrade to Elasticsearch 7.16.2.
M3
M4
RC1
-
#2130 - Upgrade to Elasticsearch 7.17.2.
The projection support through CassandraTemplate
and its reactive variant are refined supporting nested projections directly on the converter-level allowing to avoid superfluous and partial entity creation as interface projections are backed by a map. DTO projections are read directly into the DTO type.
We now use prepare(String)
to prepare CQL statements to prevent cache pollution with bind values. The Cassandra driver holds
SimpleStatement
as a cache key so that all associated bind values are kept in the prepared statement cache.
As statement options (page size, paging state, consistency level) are not retained in the PreparedStatement
when preparing plain CQL, statement options are copied during the bind
operation from the source statement to BoundStatement
.
If you wish to use the prepare(Statement)
method, then subclass the CassandraTemplate
(or its asynchronous and reactive variants) class, override the createPreparedStatementHandler(…)
hook method and provide your customized PreparedStatementHandler
to prepare statements.
Schema metadata can be now suspended through SessionFactoryFactoryBean
when performing schema actions (creation of tables, drops of tables) within the lifecycle methods. Suspending the metadata delays schema refreshes until after finishing schema actions to avoid schema agreement and therefore to speed up the schema changes.
Also, the schema refresh is now tied to whether schema metadata is enabled through the driver configuration to skip schema refresh if it is not enabled.
When using Redis 6, you can now authenticate with Redis Sentinel using ACL authentication by providing the username in addition to the Sentinel password. Both clients, Jedis and Lettuce, will use the ACL authentication method when the username is configured.
With this release we rewrote the internals of RedisMessageListenerContainer
concerning subscriptions and lifecycle state transitioning behavior. Essentially, start()
and stop()
methods are now blocking until subscriptions are fully established and on shutdown until subscriptions are unregistered.
The previous implementation suffered from potential race conditions if the container was starting up and concurrently listeners were registered. The race can no longer happen as the start()
method is guarded against concurrent calls from multiple threads and the start()
method returns once the container is fully started. As consequence, when using RedisMessageListenerContainer
within a Spring context, the context startup/shutdown phase may take a bit longer due to the prolonged synchronization.
When an aggregate contains a one to many relationship the inserts for the referenced entity now get executed using JDBC batch operations. Batch operations are only enabled when the no ids need to get generated by the database or when the database supports returning multiple ids for batched statements.
Note that some database drivers need special directives in order to benefit from batch operations. Please, check your database documentation.
You may now use the proprietary geometry data types PGpoint
, PGbox
, PGcircle
, PGline
, PGpath
, PGpolygon
, and PGlseg
offered by Postgres and they will be passed directly to the JDBC driver.
Aggregate roots that only contain an id plus collections or direct references map to a table with just the id column. In the past those couldn’t be handled by some databases. They now work with all supported databases.
Inserts for Id only properties, including those that only contain collections, are now supported for all supported databases.
If you are maintaining a Dialect
for other databases you might take a look at the SqlServerDialect
for an example how to implement that.
For derived queries you may now provide a @Lock
annotation in order to obtain pessimistic locks when executing the query.
A method declaration like this one:
interface UserRepository extends CrudRepository<User, Long> {
@Lock(LockMode.PESSIMISTIC_READ)
List<User> findByLastname(String lastname);
}
will result in a SQL query similar to this one being generated.
Select * from user u where u.lastname = lastname LOCK IN SHARE MODE
The exact syntax of the query will depend on the dialect.
Requesting a PESSIMISTIC_READ
lock might for some databases result in a PESSIMISRIC_WRITE
lock.
Null precedence (NULLS_FIRST
, NULLS_LAST
) is now supported if the underlying database supports it.
You may now supply a Sort
like this Sort.by(new Sort.Order(Sort.Direction.ASC, "name", Sort.NullHandling.NULLS_LAST))
to any method that accepts a Sort
and expect the result being properly sorted.
This includes providing such a Sort
as a part of a Pageable
.
The @Table
annotation now offers an attribute to specify a schema where the table resides.
@Table(schema = "MY_SCHEMA")
static class EntityWithSchemaFromNamingStrategy {
@Id private Long id;
}
@Table(schema = "MY_SCHEMA", name = "A_TABLE_NAME")
static class EntityWithExplicitSchema {
@Id private Long id;
}
Spring Data R2DBC can be used with R2DBC 0.9. To use R2DBC 0.9 you require an R2DBC 0.9-compatible driver and you need to upgrade the specification interface to 0.9.0.RELEASE
. When using Maven, your pom.xml
could contain the following dependencies:
<dependencies>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-spi</artifactId>
<version>0.9.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>r2dbc-postgresql</artifactId>
<version>0.9.0.RELEASE</version>
</dependency>
</dependencies>
-
M1 - Jan 14, 2022
-
M2 - Feb 18, 2022
-
M3 - Mar 18, 2022
-
RC1 - Apr 14, 2022
-
GA - May 13, 2022
-
OSS Support until: Nov 2023
-
End of Life: Aug 2025