The SQL API of DatabaseClient
offers you maximum flexibility to run any type of SQL.
DatabaseClient
provides a more narrow interface for typical ad-hoc use-cases, such as querying, inserting, updating, and deleting data.
The entry points (insert()
, select()
, update()
, and others) follow a natural naming schema based on the operation to be run.
Moving on from the entry point, the API is designed to offer only context-dependent methods that lead to a terminating method that creates and runs a SQL statement.
Spring Data R2DBC uses a R2dbcDialect
abstraction to determine bind markers, pagination support and the data types natively supported by the underlying driver.
Consider the following simple query:
Flux<Person> people = databaseClient.select()
.from(Person.class) (1)
.fetch()
.all(); (2)
-
Using
Person
with thefrom(…)
method sets theFROM
table based on mapping metadata. It also maps tabular results onPerson
result objects. -
Fetching
all()
rows returns aFlux<Person>
without limiting results.
The following example declares a more complex query that specifies the table name by name, a WHERE
condition, and an ORDER BY
clause:
Mono<Person> first = databaseClient.select()
.from("legoset") (1)
.matching(where("firstname").is("John") (2)
.and("lastname").in("Doe", "White"))
.orderBy(desc("id")) (3)
.as(Person.class)
.fetch()
.one(); (4)
-
Selecting from a table by name returns row results as
Map<String, Object>
with case-insensitive column name matching. -
The issued query declares a
WHERE
condition onfirstname
andlastname
columns to filter results. -
Results can be ordered by individual column names, resulting in an
ORDER BY
clause. -
Selecting the one result fetches only a single row. This way of consuming rows expects the query to return exactly a single result.
Mono
emits aIncorrectResultSizeDataAccessException
if the query yields more than a single result.
Tip
|
You can directly apply Projections to result documents by providing the target type via as(Class<?>) .
|
You can consume Query results in three ways:
-
Through object mapping (for example,
as(Class<T>)
) by using Spring Data’s mapping-metadata. -
As
Map<String, Object>
where column names are mapped to their value. Column names are looked up in a case-insensitive way. -
By supplying a mapping
BiFunction
for direct access to R2DBCRow
andRowMetadata
.
You can switch between retrieving a single entity and retrieving multiple entities through the following terminating methods:
-
first()
: Consume only the first row, returning aMono
. The returnedMono
completes without emitting an object if the query returns no results. -
one()
: Consume exactly one row, returning aMono
. The returnedMono
completes without emitting an object if the query returns no results. If the query returns more than one row,Mono
completes exceptionally emittingIncorrectResultSizeDataAccessException
. -
all()
: Consume all returned rows returning aFlux
. -
rowsUpdated
: Consume the number of affected rows. It is typically used withINSERT
,UPDATE
, andDELETE
statements.
You can use the select()
entry point to express your SELECT
queries.
The resulting SELECT
queries support the commonly used clauses (WHERE
and ORDER BY
) and support pagination.
The fluent API style let you chain together multiple methods while having easy-to-understand code.
To improve readability, you can use static imports that let you avoid using the 'new' keyword for creating Criteria
instances.
The Criteria
class provides the following methods, all of which correspond to SQL operators:
-
Criteria
and(String column)
: Adds a chainedCriteria
with the specifiedproperty
to the currentCriteria
and returns the newly created one. -
Criteria
or(String column)
: Adds a chainedCriteria
with the specifiedproperty
to the currentCriteria
and returns the newly created one. -
Criteria
greaterThan(Object o)
: Creates a criterion by using the>
operator. -
Criteria
greaterThanOrEquals(Object o)
: Creates a criterion by using the>=
operator. -
Criteria
in(Object… o)
: Creates a criterion by using theIN
operator for a varargs argument. -
Criteria
in(Collection<?> collection)
: Creates a criterion by using theIN
operator using a collection. -
Criteria
is(Object o)
: Creates a criterion by using column matching (property = value
). -
Criteria
isNull()
: Creates a criterion by using theIS NULL
operator. -
Criteria
isNotNull()
: Creates a criterion by using theIS NOT NULL
operator. -
Criteria
lessThan(Object o)
: Creates a criterion by using the<
operator. -
Criteria
lessThanOrEquals(Object o)
: Creates a criterion by using the⇐
operator. -
Criteria
like(Object o)
: Creates a criterion by using theLIKE
operator without escape character processing. -
Criteria
not(Object o)
: Creates a criterion by using the!=
operator. -
Criteria
notIn(Object… o)
: Creates a criterion by using theNOT IN
operator for a varargs argument. -
Criteria
notIn(Collection<?> collection)
: Creates a criterion by using theNOT IN
operator using a collection.
You can use Criteria
with SELECT
, UPDATE
, and DELETE
queries.
The select()
entry point exposes some additional methods that provide options for the query:
-
from
(Class<T>)
: Specifies the source table by using a mapped object. By default, it returns results asT
. -
from
(String)
: Specifies the source table name. By default, it returns results asMap<String, Object>
. -
as
(Class<T>)
: Maps results toT
. -
map
(BiFunction<Row, RowMetadata, T>)
: Supplies a mapping function to extract results. -
project
(String… columns)
: Specifies which columns to return. -
matching
(Criteria)
: Declares aWHERE
condition to filter results. -
orderBy
(Order)
: Declares anORDER BY
clause to sort results. -
page
(Page pageable)
: Retrieves a particular page within the result. It limits the size of the returned results and reads from an offset. -
fetch
()
: Transition call declaration to the fetch stage to declare result consumption multiplicity.
You can use the insert()
entry point to insert data. Similar to select()
, insert()
allows free-form and mapped object inserts.
Consider the following simple typed insert operation:
Mono<Void> insert = databaseClient.insert()
.into(Person.class) (1)
.using(new Person(…)) (2)
.then(); (3)
-
Using
Person
with theinto(…)
method sets theINTO
table, based on mapping metadata. It also prepares the insert statement to acceptPerson
objects for inserting. -
Provide a scalar
Person
object. Alternatively, you can supply aPublisher
to execute a stream ofINSERT
statements. This method extracts all non-null
values and inserts them. -
Use
then()
to insert an object without consuming further details. Modifying statements allow consumption of the number of affected rows or tabular results for consuming generated keys.
Inserts also support untyped operations, as the following example shows:
Mono<Void> insert = databaseClient.insert()
.into("person") (1)
.value("firstname", "John") (2)
.nullValue("lastname") (3)
.then(); (4)
-
Start an insert into the
person
table. -
Provide a non-null value for
firstname
. -
Set
lastname
tonull
. -
Use
then()
to insert an object without consuming further details. Modifying statements allow consumption of the number of affected rows or tabular results for consuming generated keys.
The insert()
entry point exposes the following additional methods to provide options for the operation:
-
into
(Class<T>)
: Specifies the target table using a mapped object. By default, it returns results asT
. -
into
(String)
: Specifies the target table name. By default, it returns results asMap<String, Object>
. -
using
(T)
: Specifies the object to insert. -
using
(Publisher<T>)
: Accepts a stream of objects to insert. -
table
(String)
: Overrides the target table name. -
value
(String, Object)
: Provides a column value to insert. -
nullValue
(String)
: Provides a null value to insert. -
map
(BiFunction<Row, RowMetadata, T>)
: Supplies a mapping function to extract results. -
then
()
: ExecutesINSERT
without consuming any results. -
fetch
()
: Transition call declaration to the fetch stage to declare result consumption multiplicity.
You can use the update()
entry point to update rows.
Updating data starts by specifying the table to update by accepting Update
specifying assignments.
It also accepts Criteria
to create a WHERE
clause.
Consider the following simple typed update operation:
Person modified = …
Mono<Void> update = databaseClient.update()
.table(Person.class) (1)
.using(modified) (2)
.then(); (3)
-
Using
Person
with thetable(…)
method sets the table to update based on mapping metadata. -
Provide a scalar
Person
object value.using(…)
accepts the modified object and derives primary keys and updates all column values. -
Use
then()
to update the rows of an object without consuming further details. Modifying statements also allow consumption of the number of affected rows.
Update also supports untyped operations, as the following example shows:
Mono<Void> update = databaseClient.update()
.table("person") (1)
.using(Update.update("firstname", "Jane")) (2)
.matching(where("firstname").is("John")) (3)
.then(); (4)
-
Update the
person
table. -
Provide a,
Update
definition of which columns to update. -
The issued query declares a
WHERE
condition onfirstname
columns to filter the rows to update. -
Use
then()
to update the rows of an object without consuming further details. Modifying statements also allow consumption of the number of affected rows.
The update()
entry point exposes the following additional methods to provide options for the operation:
-
table
(Class<T>)
: Specifies the target table byusing a mapped object. Returns results by default asT
. -
table
(String)
: Specifies the target table name. By default, it returns results asMap<String, Object>
. -
using `(T)`Specifies the object to update. It derives criteria itself.
-
using
(Update)
: Specifies the update definition. -
matching
(Criteria)
: Declares aWHERE
condition to indicate which rows to update. -
then
()
: Runs theUPDATE
without consuming any results. -
fetch
()
: Transition call declaration to the fetch stage to fetch the number of updated rows.
You can use the delete()
entry point to delete rows.
Removing data starts with a specification of the table to delete from and, optionally, accepts a Criteria
to create a WHERE
clause.
Consider the following simple insert operation:
Mono<Void> delete = databaseClient.delete()
.from(Person.class) (1)
.matching(where("firstname").is("John") (2)
.and("lastname").in("Doe", "White"))
.then(); (3)
-
Using
Person
with thefrom(…)
method sets theFROM
table, based on mapping metadata. -
The issued query declares a
WHERE
condition onfirstname
andlastname
columns to filter rows to delete. -
Use
then()
to delete rows from an object without consuming further details. Modifying statements also allow consumption of the number of affected rows.
The delete()
entry point exposes the following additional methods to provide options for the operation:
-
from
(Class<T>)
: Specifies the target table by using a mapped object. By default, it returns results asT
. -
from
(String)
: Specifies the target table name. By default, it returns results asMap<String, Object>
. -
matching
(Criteria)
: Declares aWHERE
condition to define the rows to delete. -
then
()
: Runs theDELETE
without consuming any results. -
fetch
()
: Transition call declaration to the fetch stage to fetch the number of deleted rows.