liveBook · Manning

Spring Data R2DBC

As explained in Spring in Action, Sixth Edition

Spring Data R2DBC is a Spring Data project that provides repository-based persistence for relational databases through the Reactive Relational Database Connectivity API.

Spring Data R2DBC provides repository-based persistence for relational databases through R2DBC. Unlike JDBC, R2DBC uses Reactive Streams for nonblocking data access. Spring Data R2DBC supplies repository support similar to Spring Data JDBC, but its handling of relationships calls for a different domain design. section 13.1 section 13.4

To start a relational persistence project:

  • Add the spring-boot-starter-data-r2dbc dependency, or select Spring Data R2DBC in Spring Initializr. section 13.1
  • Add a relational database and its matching R2DBC driver. An in-memory H2 setup uses both the H2 database library and the H2 R2DBC driver. section 13.1
  • Define entities and matching tables. Give a new entity a database-generated Long ID: a non-null ID is treated as an update when a repository saves it. section 13.1.1

Consider ingredients, tacos, and orders. Their entities need setters for persisted properties. Direct entity relationships are not supported here, so a taco stores ingredient IDs in a Set<Long> rather than a collection of Ingredient objects. Orders likewise store taco IDs. Persisting a taco as part of an order aggregate requires more work than it does with Spring Data JDBC. section 13.1.1 section 13.1.2

Listing 13.2 The Taco entity class for R2DBC persistence
package tacos;
 
import java.util.HashSet;
import java.util.Set;
import org.springframework.data.annotation.Id;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
 
@Data
@NoArgsConstructor
@RequiredArgsConstructor
public class Taco {
 
  @Id
  private Long id;
  
  private @NonNull String name;
  
  private Set<Long> ingredientIds = new HashSet<>();
  
  public void addIngredient(Ingredient ingredient) {
    ingredientIds.add(ingredient.getId());
  }
  
}

The Taco entity shows the practical workaround: ingredientIds holds unique database IDs, and addIngredient copies an ingredient’s ID into that set. section 13.1.1

Create an interface extending ReactiveCrudRepository for each entity. Repository methods return reactive types: findAll() returns a Flux of orders, while a derived finder such as findBySlug(String slug) returns a Mono of one ingredient. Subscribe to a Flux to start its flow of data. section 13.1.2

Listing 13.6 Persisting Ingredient objects with a reactive repository
package tacos.data;
 
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Mono;
import tacos.Ingredient;
 
public interface IngredientRepository 
       extends ReactiveCrudRepository<Ingredient, Long> {
  
  Mono<Ingredient> findBySlug(String slug);
  
}

IngredientRepository shows both the ReactiveCrudRepository declaration and a slug-based finder returning Mono<Ingredient>. section 13.1.2

Test a generated repository

Annotate an integration test with @DataR2dbcTest to make generated repositories available for injection. Save test ingredients, then use StepVerifier to check how many were saved, inspect the items returned by findAll(), and verify that findBySlug("FLTO") emits the expected flour-tortilla ingredient. StepVerifier subscribes to the publisher as it checks it. section 13.1.3

How Spring in Action, Sixth Edition covers it

How deep it goes
Works through dependencies, entity design, repository interfaces, and integration tests; identifies direct relationship support as a limitation.
Examples
Uses H2-backed ingredient, taco, and order entities, a slug finder, and an ingredient repository integration test.
What it assumes
Introduces R2DBC by comparison with JDBC while using Java entity classes, Maven dependencies, and reactive types in the implementation.
What you can do after
Build it from scratch with Spring Data R2DBC repositories, ID-based entity references, and a StepVerifier integration test.
How it connects
Connects R2DBC to Reactive Streams, Spring Data JDBC, reactive repositories, and StepVerifier.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Spring in Action, Sixth Edition. The section links point to the parts of the book it draws on.