Skip to content
Bluetape4k docs1.11

R2DBC ecosystem path

Latest stable Based on Bluetape4k release 1.11.0

The same database can have several useful entry points.

RequirementRecommended starting point
Spring Data entity mapping and coroutine CRUDbluetape4k-spring-boot-r2dbc
Raw SQL, binding, custom row mapping, connection and transaction helpersbluetape4k-r2dbc
Kotlin table DSL, DDL/DML, and repository abstractionsbluetape4k-exposed R2DBC
Blocking-driver ecosystem and a simpler transaction modelbluetape4k-jdbc
Object graphs, dirty checking, and a persistence contextbluetape4k-hibernate

R2DBC is not inherently better than JDBC. The full call path must benefit from non-blocking I/O, and the chosen database driver must support the required behavior.

Start with R2dbcEntityOperations, Query, Criteria, Flow, and suspending cardinality. The in-module coroutines.blog application demonstrates the entity→repository→controller path.

Recommended order:

  1. Whole-list and one-row reads in PostRepository
  2. Filtered Flow and count in CommentRepository
  3. The CRUD cycle in R2dbcEntityOperationsExtensionsTest
  4. The WebFlux boundary in PostControllerTest

Move to bluetape4k-r2dbc for joins, DTO projections, or vendor-specific SQL that do not fit entity operations. Its core R2DBC manual explains connection pools, transaction lifecycle, typed null binding, and raw SQL mapping.

Both modules can coexist. Keep straightforward entity CRUD here and implement only complex queries with R2dbcClient or DatabaseClient.

Evaluate the R2DBC modules in bluetape4k-exposed when you want Kotlin table and column DSLs with repository patterns. Spring Data entity mapping and Exposed table mapping are separate models; avoid making both own the same aggregate without a clear boundary.

The Exposed R2DBC Workshop provides runnable exercises for:

  • Table and schema definitions
  • Coroutine transactions and CRUD
  • Repository and domain mapping
  • Spring WebFlux integration
  • Real-database tests and operational patterns

JDBC may be a better fit when its driver and library ecosystem already covers the application and implementation simplicity matters more than a fully non-blocking request path. Virtual threads or an explicit Dispatchers.IO boundary are also valid options. R2DBC fits when the path remains non-blocking from WebFlux through the driver and handles many concurrent I/O operations.

The JDBC manual covers blocking connection, transaction, and statement lifecycles. Choose from application call paths and driver maturity rather than technology labels.

  • Tests distinguish one, oneOrNull, first, and Flow cardinality.
  • Update and delete counts are compared with domain expectations.
  • Transaction ownership and connection/pool ownership are documented.
  • H2 and production-driver tests have separate evidence scopes.
  • Raw SQL queries are separated from entity operations.
  • Blocking libraries are not called directly inside a suspending function.

After choosing the appropriate level, implement one small repository from the first chapter of that manual. Move to another abstraction only when the feature needs it.