Skip to content

Spring Data 2021.2 (Raj) Release Notes

Mark Paluch edited this page Sep 12, 2023 · 3 revisions

General Themes

  • Direct projections

  • Property-specific converters

Participating Modules

Details

New and Noteworthy

Spring Data Commons - 2.7

Configuration of class loader in SimpleTypeInformationMapper

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.

Infrastructure to introspect a projection type

EntityProjection provides an API to introspect projection types in the context of an entity to determine which property paths to consider during loading.

Infrastructure to support property-specific value converters

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;
}

Spring Data JPA - 2.7

Add support for DTO projections on derived query methods.

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.

JpaRepository.getReferenceById replaces JpaRepository.getById

We introduced JpaRepository.getReferenceById as a replacement for JpaRepository.getById, which should make the difference to JpaRepository.findById more obvious.

Ignore fields with Optional.empty when performing Query by Example.

Improved support for IdClass by fixing corner cases that failed in the past.

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.

exists method in JpaSpecificationExecutor

You can now check for the existence of entities specified by a Specification using JpaSpecificationExecutor.exists.

ignoreCase operators now use lower() functions across the board

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.

Spring Data MongoDB - 3.4

Direct projections

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.

Repository Update Methods

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);

Property specific converters

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<>() { ... });
  })
})

Spring Data Neo4j - 6.3

Impersonation

Spring Data Elasticsearch - 4.4

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

  • #2077 - Upgrade to Elasticsearch 7.17.0.

  • #2043 - Allow to index documents to different indices in a bulk request.

M4

  • #2025 - Potential throwing of the blocking exception.

  • #2108 - Upgrade to Elasticsearch 7.17.1.

RC1

  • #2130 - Upgrade to Elasticsearch 7.17.2.

Spring Data Couchbase - 4.4

Spring Data for Apache Cassandra - 3.4

Direct projections

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.

CQL Preparation Method Changed

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.

Allow suspending schema metadata while performing SchemaAction

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.

Spring Data for Apache Geode - 2.7

Spring Data Redis - 2.7

ACL support for Sentinel Configuration

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.

Revised RedisMessageListenerContainer

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.

Spring Data KeyValue - 2.7

Spring Data REST - 3.7

Spring Data LDAP - 2.7

Spring Data JDBC - 2.4

Multiple inserts for a single aggregate get batched.

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.

Support for Postgres Geometry Data Types.

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.

Full Support for Id only entities.

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.

@Lock for derived queries

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.

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.

Support for H2 version 2.0.202.

Specify a schema in a @Table annotation.

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;
}
This works with or without an explicitly specified table name.
@Table(schema = "MY_SCHEMA", name = "A_TABLE_NAME")
static class EntityWithExplicitSchema {
    @Id private Long id;
}

Spring Data R2DBC - 1.5

Compatibility with R2DBC 0.9

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>

Spring Data Envers - 2.7

Release Dates

  • 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