Merge branch '6.0.x'

This commit is contained in:
Juergen Hoeller 2023-08-16 16:55:01 +02:00
commit 3f79b267b1
2 changed files with 36 additions and 34 deletions

View File

@ -11,11 +11,13 @@ specification effort to standardize access to SQL databases using reactive patte
The Spring Framework's R2DBC abstraction framework consists of two different packages: The Spring Framework's R2DBC abstraction framework consists of two different packages:
* `core`: The `org.springframework.r2dbc.core` package contains the `DatabaseClient` * `core`: The `org.springframework.r2dbc.core` package contains the `DatabaseClient`
class plus a variety of related classes. See xref:data-access/r2dbc.adoc#r2dbc-core[Using the R2DBC Core Classes to Control Basic R2DBC Processing and Error Handling]. class plus a variety of related classes. See
xref:data-access/r2dbc.adoc#r2dbc-core[Using the R2DBC Core Classes to Control Basic R2DBC Processing and Error Handling].
* `connection`: The `org.springframework.r2dbc.connection` package contains a utility class * `connection`: The `org.springframework.r2dbc.connection` package contains a utility class
for easy `ConnectionFactory` access and various simple `ConnectionFactory` implementations for easy `ConnectionFactory` access and various simple `ConnectionFactory` implementations
that you can use for testing and running unmodified R2DBC. See xref:data-access/r2dbc.adoc#r2dbc-connections[Controlling Database Connections]. that you can use for testing and running unmodified R2DBC. See
xref:data-access/r2dbc.adoc#r2dbc-connections[Controlling Database Connections].
[[r2dbc-core]] [[r2dbc-core]]
@ -31,6 +33,7 @@ including error handling. It includes the following topics:
* xref:data-access/r2dbc.adoc#r2dbc-DatabaseClient-filter[Statement Filters] * xref:data-access/r2dbc.adoc#r2dbc-DatabaseClient-filter[Statement Filters]
* xref:data-access/r2dbc.adoc#r2dbc-auto-generated-keys[Retrieving Auto-generated Keys] * xref:data-access/r2dbc.adoc#r2dbc-auto-generated-keys[Retrieving Auto-generated Keys]
[[r2dbc-DatabaseClient]] [[r2dbc-DatabaseClient]]
=== Using `DatabaseClient` === Using `DatabaseClient`
@ -43,8 +46,9 @@ SQL and extract results. The `DatabaseClient` class:
* Runs SQL queries * Runs SQL queries
* Update statements and stored procedure calls * Update statements and stored procedure calls
* Performs iteration over `Result` instances * Performs iteration over `Result` instances
* Catches R2DBC exceptions and translates them to the generic, more informative, exception * Catches R2DBC exceptions and translates them to the generic, more informative,
hierarchy defined in the `org.springframework.dao` package. (See xref:data-access/dao.adoc#dao-exceptions[Consistent Exception Hierarchy].) exception hierarchy defined in the `org.springframework.dao` package.
(See xref:data-access/dao.adoc#dao-exceptions[Consistent Exception Hierarchy].)
The client has a functional, fluent API using reactive types for declarative composition. The client has a functional, fluent API using reactive types for declarative composition.
@ -250,7 +254,6 @@ Kotlin::
---- ----
====== ======
[[r2dbc-DatabaseClient-mapping-null]] [[r2dbc-DatabaseClient-mapping-null]]
.What about `null`? .What about `null`?
**** ****
@ -315,10 +318,10 @@ The following example shows parameter binding for a query:
[source,java] [source,java]
---- ----
db.sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)") db.sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
.bind("id", "joe") .bind("id", "joe")
.bind("name", "Joe") .bind("name", "Joe")
.bind("age", 34); .bind("age", 34);
---- ----
.R2DBC Native Bind Markers .R2DBC Native Bind Markers
@ -327,7 +330,7 @@ R2DBC uses database-native bind markers that depend on the actual database vendo
As an example, Postgres uses indexed markers, such as `$1`, `$2`, `$n`. As an example, Postgres uses indexed markers, such as `$1`, `$2`, `$n`.
Another example is SQL Server, which uses named bind markers prefixed with `@`. Another example is SQL Server, which uses named bind markers prefixed with `@`.
This is different from JDBC, which requires `?` as bind markers. This is different from JDBC which requires `?` as bind markers.
In JDBC, the actual drivers translate `?` bind markers to database-native In JDBC, the actual drivers translate `?` bind markers to database-native
markers as part of their statement execution. markers as part of their statement execution.
@ -363,7 +366,7 @@ Java::
tuples.add(new Object[] {"Ann", 50}); tuples.add(new Object[] {"Ann", 50});
client.sql("SELECT id, name, state FROM table WHERE (name, age) IN (:tuples)") client.sql("SELECT id, name, state FROM table WHERE (name, age) IN (:tuples)")
.bind("tuples", tuples); .bind("tuples", tuples);
---- ----
Kotlin:: Kotlin::
@ -375,7 +378,7 @@ Kotlin::
tuples.add(arrayOf("Ann", 50)) tuples.add(arrayOf("Ann", 50))
client.sql("SELECT id, name, state FROM table WHERE (name, age) IN (:tuples)") client.sql("SELECT id, name, state FROM table WHERE (name, age) IN (:tuples)")
.bind("tuples", tuples) .bind("tuples", tuples)
---- ----
====== ======
@ -390,7 +393,7 @@ Java::
[source,java,indent=0,subs="verbatim,quotes",role="primary"] [source,java,indent=0,subs="verbatim,quotes",role="primary"]
---- ----
client.sql("SELECT id, name, state FROM table WHERE age IN (:ages)") client.sql("SELECT id, name, state FROM table WHERE age IN (:ages)")
.bind("ages", Arrays.asList(35, 50)); .bind("ages", Arrays.asList(35, 50));
---- ----
Kotlin:: Kotlin::
@ -402,7 +405,7 @@ Kotlin::
tuples.add(arrayOf("Ann", 50)) tuples.add(arrayOf("Ann", 50))
client.sql("SELECT id, name, state FROM table WHERE age IN (:ages)") client.sql("SELECT id, name, state FROM table WHERE age IN (:ages)")
.bind("tuples", arrayOf(35, 50)) .bind("tuples", arrayOf(35, 50))
---- ----
====== ======
@ -429,9 +432,9 @@ Java::
[source,java,indent=0,subs="verbatim,quotes",role="primary"] [source,java,indent=0,subs="verbatim,quotes",role="primary"]
---- ----
client.sql("INSERT INTO table (name, state) VALUES(:name, :state)") client.sql("INSERT INTO table (name, state) VALUES(:name, :state)")
.filter((s, next) -> next.execute(s.returnGeneratedValues("id"))) .filter((s, next) -> next.execute(s.returnGeneratedValues("id")))
.bind("name", …) .bind("name", …)
.bind("state", …); .bind("state", …);
---- ----
Kotlin:: Kotlin::
@ -439,9 +442,9 @@ Kotlin::
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
---- ----
client.sql("INSERT INTO table (name, state) VALUES(:name, :state)") client.sql("INSERT INTO table (name, state) VALUES(:name, :state)")
.filter { s: Statement, next: ExecuteFunction -> next.execute(s.returnGeneratedValues("id")) } .filter { s: Statement, next: ExecuteFunction -> next.execute(s.returnGeneratedValues("id")) }
.bind("name", …) .bind("name", …)
.bind("state", …) .bind("state", …)
---- ----
====== ======
@ -455,10 +458,10 @@ Java::
[source,java,indent=0,subs="verbatim,quotes",role="primary"] [source,java,indent=0,subs="verbatim,quotes",role="primary"]
---- ----
client.sql("INSERT INTO table (name, state) VALUES(:name, :state)") client.sql("INSERT INTO table (name, state) VALUES(:name, :state)")
.filter(statement -> s.returnGeneratedValues("id")); .filter(statement -> s.returnGeneratedValues("id"));
client.sql("SELECT id, name, state FROM table") client.sql("SELECT id, name, state FROM table")
.filter(statement -> s.fetchSize(25)); .filter(statement -> s.fetchSize(25));
---- ----
Kotlin:: Kotlin::
@ -466,10 +469,10 @@ Kotlin::
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
---- ----
client.sql("INSERT INTO table (name, state) VALUES(:name, :state)") client.sql("INSERT INTO table (name, state) VALUES(:name, :state)")
.filter { statement -> s.returnGeneratedValues("id") } .filter { statement -> s.returnGeneratedValues("id") }
client.sql("SELECT id, name, state FROM table") client.sql("SELECT id, name, state FROM table")
.filter { statement -> s.fetchSize(25) } .filter { statement -> s.fetchSize(25) }
---- ----
====== ======
@ -593,7 +596,7 @@ Java::
[source,java,indent=0,subs="verbatim,quotes",role="primary"] [source,java,indent=0,subs="verbatim,quotes",role="primary"]
---- ----
Mono<Integer> generatedId = client.sql("INSERT INTO table (name, state) VALUES(:name, :state)") Mono<Integer> generatedId = client.sql("INSERT INTO table (name, state) VALUES(:name, :state)")
.filter(statement -> s.returnGeneratedValues("id")) .filter(statement -> s.returnGeneratedValues("id"))
.map(row -> row.get("id", Integer.class)) .map(row -> row.get("id", Integer.class))
.first(); .first();
@ -605,7 +608,7 @@ Kotlin::
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
---- ----
val generatedId = client.sql("INSERT INTO table (name, state) VALUES(:name, :state)") val generatedId = client.sql("INSERT INTO table (name, state) VALUES(:name, :state)")
.filter { statement -> s.returnGeneratedValues("id") } .filter { statement -> s.returnGeneratedValues("id") }
.map { row -> row.get("id", Integer.class) } .map { row -> row.get("id", Integer.class) }
.awaitOne() .awaitOne()
@ -672,7 +675,6 @@ Kotlin::
[[r2dbc-ConnectionFactoryUtils]] [[r2dbc-ConnectionFactoryUtils]]
=== Using `ConnectionFactoryUtils` === Using `ConnectionFactoryUtils`
The `ConnectionFactoryUtils` class is a convenient and powerful helper class The `ConnectionFactoryUtils` class is a convenient and powerful helper class
that provides `static` methods to obtain connections from `ConnectionFactory` that provides `static` methods to obtain connections from `ConnectionFactory`
and close connections (if necessary). and close connections (if necessary).

View File

@ -101,13 +101,13 @@ dependencies {
api("org.apache.httpcomponents.client5:httpclient5:5.2.1") api("org.apache.httpcomponents.client5:httpclient5:5.2.1")
api("org.apache.httpcomponents.core5:httpcore5-reactive:5.2.1") api("org.apache.httpcomponents.core5:httpcore5-reactive:5.2.1")
api("org.apache.poi:poi-ooxml:5.2.3") api("org.apache.poi:poi-ooxml:5.2.3")
api("org.apache.tomcat.embed:tomcat-embed-core:10.1.10") api("org.apache.tomcat.embed:tomcat-embed-core:10.1.12")
api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.10") api("org.apache.tomcat.embed:tomcat-embed-websocket:10.1.12")
api("org.apache.tomcat:tomcat-util:10.1.10") api("org.apache.tomcat:tomcat-util:10.1.12")
api("org.apache.tomcat:tomcat-websocket:10.1.10") api("org.apache.tomcat:tomcat-websocket:10.1.12")
api("org.aspectj:aspectjrt:1.9.19") api("org.aspectj:aspectjrt:1.9.20")
api("org.aspectj:aspectjtools:1.9.19") api("org.aspectj:aspectjtools:1.9.20")
api("org.aspectj:aspectjweaver:1.9.19") api("org.aspectj:aspectjweaver:1.9.20")
api("org.assertj:assertj-core:3.24.2") api("org.assertj:assertj-core:3.24.2")
api("org.awaitility:awaitility:4.2.0") api("org.awaitility:awaitility:4.2.0")
api("org.bouncycastle:bcpkix-jdk18on:1.72") api("org.bouncycastle:bcpkix-jdk18on:1.72")