[[r2dbc.datbaseclient.fluent-api]]
[[r2dbc.entityoperations]]
= R2dbcEntityOperations Data Access API

`R2dbcEntityTemplate` is the central entrypoint for Spring Data R2DBC.
It provides direct entity-oriented methods and a more narrow, fluent 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.

NOTE: All terminal methods return always a `Publisher` type that represents the desired operation.
The actual statements are sent to the database upon subscription.

[[r2dbc.entityoperations.save-insert]]
== Methods for Inserting and Updating Entities

There are several convenient methods on `R2dbcEntityTemplate` for saving and inserting your objects.
To have more fine-grained control over the conversion process, you can register Spring converters with `R2dbcCustomConversions` -- for example  `Converter<Person, OutboundRow>` and `Converter<Row, Person>`.

The simple case of using the save operation is to save a POJO. In this case, the table name is determined by name (not fully qualified) of the class.
You may also call the save operation with a specific collection name.
You can use mapping metadata to override the collection in which to store the object.

When inserting or saving, if the `Id` property is not set, the assumption is that its value will be auto-generated by the database.
Consequently, for auto-generation the type of the `Id` property or field in your class must be a `Long`, or `Integer`.

The following example shows how to insert a row and retrieving its contents:

.Inserting and retrieving entities using the `R2dbcEntityTemplate`
====
[source,java,indent=0]
----
include::../{example-root}/R2dbcEntityTemplateSnippets.java[tag=insertAndSelect]
----
====

The following insert and update operations are available:

A similar set of insert operations is also available:

* `Mono<T>` *insert* `(T objectToSave)`: Insert the object to the default table.
* `Mono<T>` *update* `(T objectToSave)`: Insert the object to the default table.

Table names can be customized by using the fluent API.

[[r2dbc.entityoperations.selecting]]
== Selecting Data

The `select(…)` and `selectOne(…)` methods on `R2dbcEntityTemplate` are used to select data from a table.
Both methods take a <<r2dbc.datbaseclient.fluent-api.criteria,`Query`>> object that defines the field projection, the `WHERE` clause, the `ORDER BY` clause and limit/offset pagination.
Limit/offset functionality is transparent to the application regardless of the underlying database.
This functionality is supported by the <<r2dbc.drivers,`R2dbcDialect` abstraction>> to cater for differences between the individual SQL flavors.

.Selecting entities using the `R2dbcEntityTemplate`
====
[source,java,indent=0]
----
include::../{example-root}/R2dbcEntityTemplateSnippets.java[tag=select]
----
====

[[r2dbc.entityoperations.fluent-api]]
== Fluent API

This section explains the fluent API usage.
Consider the following simple query:

====
[source,java,indent=0]
----
include::../{example-root}/R2dbcEntityTemplateSnippets.java[tag=simpleSelect]
----
<1> Using `Person` with the `select(…)` method maps tabular results on `Person` result objects.
<2> Fetching `all()` rows returns a `Flux<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:

====
[source,java,indent=0]
----
include::../{example-root}/R2dbcEntityTemplateSnippets.java[tag=fullSelect]
----
<1> Selecting from a table by name returns row results using the given domain type.
<2> The issued query declares a `WHERE` condition on `firstname` and `lastname` columns to filter results.
<3> Results can be ordered by individual column names, resulting in an `ORDER BY` clause.
<4> 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 a `IncorrectResultSizeDataAccessException` if the query yields more than a single result.
====

TIP: You can directly apply <<projections,Projections>> to results by providing the target type via `select(Class<?>)`.

You can switch between retrieving a single entity and retrieving multiple entities through the following terminating methods:

* `first()`: Consume only the first row, returning a `Mono`.
The returned `Mono` completes without emitting an object if the query returns no results.
* `one()`: Consume exactly one row, returning a `Mono`.
The returned `Mono` completes without emitting an object if the query returns no results.
If the query returns more than one row, `Mono` completes exceptionally emitting `IncorrectResultSizeDataAccessException`.
* `all()`: Consume all returned rows returning a `Flux`.
* `count()`: Apply a count projection returning `Mono<Long>`.
* `exists()`: Return whether the query yields any rows by returning `Mono<Boolean>`.

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.

[[r2dbc.datbaseclient.fluent-api.criteria]]
=== Methods for the Criteria Class

The `Criteria` class provides the following methods, all of which correspond to SQL operators:

* `Criteria` *and* `(String column)`: Adds a chained `Criteria` with the specified `property` to the current `Criteria` and returns the newly created one.
* `Criteria` *or* `(String column)`: Adds a chained `Criteria` with the specified `property` to the current `Criteria` 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 the `IN` operator for a varargs argument.
* `Criteria` *in* `(Collection<?> collection)`: Creates a criterion by using the `IN` operator using a collection.
* `Criteria` *is* `(Object o)`: Creates a criterion by using column matching (`property = value`).
* `Criteria` *isNull* `()`: Creates a criterion by using the `IS NULL` operator.
* `Criteria` *isNotNull* `()`: Creates a criterion by using the `IS 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 the `LIKE` 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 the `NOT IN` operator for a varargs argument.
* `Criteria` *notIn* `(Collection<?> collection)`: Creates a criterion by using the `NOT IN` operator using a collection.

You can use `Criteria` with `SELECT`, `UPDATE`, and `DELETE` queries.

[[r2dbc.entityoperations.fluent-api.insert]]
== Inserting Data

You can use the `insert()` entry point to insert data.

Consider the following simple typed insert operation:

====
[source,java,indent=0]
----
include::../{example-root}/R2dbcEntityTemplateSnippets.java[tag=insert]
----
<1> Using `Person` with the `into(…)` method sets the `INTO` table, based on mapping metadata.
It also prepares the insert statement to accept `Person` objects for inserting.
<2> Provide a scalar `Person` object.
Alternatively, you can supply a `Publisher` to run a stream of `INSERT` statements.
This method extracts all non-`null` values and inserts them.
====

[[r2dbc.entityoperations.fluent-api.update]]
== Updating Data

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 `Query` to create a `WHERE` clause.

Consider the following simple typed update operation:

====
[source,java]
----
Person modified = …

include::../{example-root}/R2dbcEntityTemplateSnippets.java[tag=update]
----
<1> Update `Person` objects and apply mapping based on mapping metadata.
<2> Set a different table name by calling the `inTable(…)` method.
<3> Specify a query that translates into a `WHERE` clause.
<4> Apply the `Update` object.
Set in this case `age` to `42` and return the number of affected rows.
====

[[r2dbc.entityoperations.fluent-api.delete]]
== Deleting Data

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:

====
[source,java]
----
include::../{example-root}/R2dbcEntityTemplateSnippets.java[tag=delete]
----
<1> Delete `Person` objects and apply mapping based on mapping metadata.
<2> Set a different table name by calling the `from(…)` method.
<3> Specify a query that translates into a `WHERE` clause.
<4> Apply the delete operation and return the number of affected rows.
====
