Skip to content
Bluetape4k docs1.11

SQL execution and parameter binding

Latest stable Based on Bluetape4k release 1.11.0

DatabaseClient.execute returns Spring’s GenericExecuteSpec. R2dbcClient.execute<T> maps rows through the stored MappingR2dbcConverter. Choose direct DatabaseClient mapping for explicit SQL projections and the typed path to reuse Spring Data mapping metadata.

val users = client
.execute<User>("SELECT * FROM users WHERE active = :active")
.bind("active", true)
.fetch()
.flow()
.toList()

Use awaitOne() for exactly one row, awaitOneOrNull() for zero or one, and flow() for multiple rows. Match the terminal operation to the query’s cardinality contract.

val spec = client.databaseClient
.sql("SELECT * FROM users WHERE username = :username AND active = :active")
.bindMap(mapOf("username" to "jsmith", "active" to true))

bindMap converts entries to R2DBC parameters. A raw null has no database type and fails with IllegalArgumentException.

client.databaseClient
.sql("UPDATE users SET description = :description WHERE user_id = :id")
.bindMap(mapOf("description" to typedNullParameter<String>()))
.bind("id", 1)
.fetch()
.awaitRowsUpdated()

For a single value, use bindNullable<String>("description", value). In both cases, the null retains its target type.

Spring R2DBC uses zero-based indexed binding.

client.databaseClient
.sql("SELECT name FROM users WHERE username = ? AND active = ?")
.bindIndexedMap(mapOf(0 to "jsmith", 1 to true))
.map<String> { row, _ -> row.get("name", String::class.java)!! }
.awaitOne()

bindIndexedMap rejects negative indexes and raw nulls. Placeholder syntax varies by driver, so verify ? or $1 behavior with the selected driver rather than mixing styles.

The 1.11.0 README mentions awaitList, awaitSingleAsMap, awaitCount, and awaitExists, but those names are absent from the release source. This chapter uses the verified Spring R2DBC operations from ExecuteTest: awaitOne, awaitOneOrNull, flow, and awaitRowsUpdated.

Driver and Spring exceptions propagate. Do not retry every backend failure; consider transaction state, idempotency, and the timeout budget. Preserve Flow cancellation instead of converting it to a fallback value.

Continue to CRUD and row mapping.