All pages
Powered by GitBook
1 of 25

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Connector/R2DBC

Learn about MariaDB R2DBC Connector for Java. This guide covers reactive, non-blocking database operations, setup, and integrating with Spring Data R2DBC for efficient data access.

MariaDB Connector/R2DBC is the reactive, non-blocking R2DBC driver for connecting Java applications to MariaDB and MySQL databases. It can be used with the native R2DBC API or with the Spring Data framework.

About MariaDB Connector/R2DBC

MariaDB Connector/R2DBC enables Java applications to connect to MariaDB using the non-blocking R2DBC API, with a native R2DBC implementation and Spring Data R2DBC framework integration.

MariaDB Connector/R2DBC Connection Parameters

MariaDB Connector/R2DBC connection parameters cover SSL mode, authentication plugins, autocommit, transaction replay, timezone handling, and prepared statement options.

Use MariaDB Connector/R2DBC directly through the native R2DBC API for reactive, non-blocking database operations with fine-grained control over data access in Java applications.

Integrate MariaDB Connector/R2DBC with the Spring Data framework for reactive, non-blocking data access using Spring Data R2DBC in modern Java applications.

This page is: Copyright © 2026 MariaDB. All rights reserved.

Using the Native R2DBC API of MariaDB Connector/R2DBC

Learn to use MariaDB Connector/R2DBC's native API. This guide details direct interaction for reactive, non-blocking database operations, offering fine-grained control over data access in Java applicat

Use MariaDB Connector/R2DBC directly through the native R2DBC API for reactive, non-blocking database access with fine-grained control.

Application development with the MariaDB Connector/R2DBC native API covers building Java projects with Maven or JAR, adding the connector to the classpath, and running compiled applications.

Using the Native R2DBC API of MariaDB Connector/R2DBC
Using the Spring Data Framework with MariaDB Connector/R2DBC
Batch operations with the MariaDB Connector/R2DBC native API group multiple DML statements into a single io.r2dbc.spi.Batch to reduce per-statement network overhead.

Connecting to MariaDB with the native R2DBC API uses MariadbConnectionConfiguration and MariadbConnectionFactory to create and manage reactive client connections via io.r2dbc.spi.Connection.

The MariaDB Connector/R2DBC native API supports connection pooling via r2dbc-pool, holding reactive connections open for reuse and configuring them with ConnectionPoolConfiguration.

DDL operations with the MariaDB Connector/R2DBC native API execute schema statements such as CREATE TABLE and ALTER TABLE reactively using io.r2dbc.spi.Statement and io.r2dbc.spi.Result.

DML with the MariaDB Connector/R2DBC native API executes INSERT, UPDATE, DELETE, and SELECT reactively using io.r2dbc.spi.Statement, Result, Row, and RowMetadata classes.

Install MariaDB Connector/R2DBC via Maven by adding the r2dbc-mariadb dependency to pom.xml, or manually by downloading the JAR and adding it to the Java CLASSPATH alongside r2dbc-pool.

Complete Java code example using the MariaDB Connector/R2DBC native API to query a MariaDB table with MariadbConnectionFactory and reactive Flux result handling.

Set up the test database, contact table, and user account required by the MariaDB Connector/R2DBC native API code examples in this documentation section.

The MariaDB Connector/R2DBC native API requires manual subscription for beginTransaction, commitTransaction, and rollbackTransaction; Spring Data R2DBC provides managed transactions.

This page is: Copyright © 2026 MariaDB. All rights reserved.

Application Development with MariaDB Connector/R2DBC (Native API)
Batch Operations with MariaDB Connector/R2DBC (Native API)
Connect with MariaDB Connector/R2DBC (Native API)
Connection Pools with MariaDB Connector/R2DBC (Native API)
DDL with MariaDB Connector/R2DBC (Native API)
DML with MariaDB Connector/R2DBC (Native API)
Install MariaDB Connector/R2DBC
R2DBC Code Example (Native API)
Setup for Connector/R2DBC Examples (Native API)
Transactions with MariaDB Connector/R2DBC (Native API)

About MariaDB Connector/R2DBC

MariaDB Connector/R2DBC enables Java applications to connect to MariaDB using the non-blocking R2DBC API, with a native R2DBC implementation and Spring Data R2DBC framework integration.

Browse & download the latest MariaDB connectors

The most recent release of is:

Overview

Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes the R2DBC API more scalable than Java's standard JDBC API. MariaDB Connector/R2DBC has a native R2DBC implementation and the Spring Data R2DBC framework.

Connector
MariaDB Connector/R2DBC

The following versions of MariaDB Connector/R2DBC have reached the End of Life and are no longer supported:

  • MariaDB Connector/R2DBC 1.0

  • MariaDB Connector/R2DBC 1.1

Users are encouraged to upgrade to the next available supported version.

Current connector supporting 1.0.0 R2DBC spec is:

The R2DBC API relies on reactive data streams, which provide many benefits over standard JDBC:

  • Reactive: R2DBC uses an event-driven, non-blocking, and functional programming model.

  • Scalable: R2DBC is more scalable than standard JDBC because it allows the runtime to handle concurrency and scheduling.

  • Fast: R2DBC streams results, which can improve performance.

For details on how to use MariaDB Connector/R2DBC, choose a supported framework:

Parameter
Description

This page is: Copyright © 2026 MariaDB. All rights reserved.

Setup for Connector/R2DBC Examples (Native API)

Set up the test database, contact table, and user account required by the MariaDB Connector/R2DBC native API code examples in this documentation section.

Overview

The examples in this MariaDB Connector/R2DBC documentation depend on a database test and table contact.

Create the Schema

  1. Create a test database if one does not exist with the CREATE DATABASE statement:

CREATE DATABASE IF NOT EXISTS test;
  1. Create an example table test.contact with the CREATE TABLE statement:

CREATE TABLE IF NOT EXISTS test.contact(
   id INT PRIMARY KEY AUTO_INCREMENT,
   first_name VARCHAR(25),
   last_name VARCHAR(25),
   email VARCHAR(25)) ENGINE=InnoDB;

Create the User

  1. Create a user account to test connectivity with the CREATE USER statement:

  1. Ensure that the user account has privileges to access the tables with the GRANT statement:

This page is: Copyright © 2026 MariaDB. All rights reserved.

Application Development with MariaDB Connector/R2DBC (Native API)

Application development with MariaDB Connector/R2DBC native API covers building Java projects with Maven or JAR, adding the connector to the classpath, and running compiled applications.

Methods for building projects with MariaDB Connector/R2DBC vary depending on the installation method you use.

Building with Maven

When building your Java application with Maven, the build downloads and installs the relevant JAR dependencies, and compiles your project:

Build the package:

$ mvn package

Run the application:

$ java -jar target/app.jar

Building with JAR

  1. To build your Java application from a download:

  2. Add your application and the JAR for MariaDB Connector/R2DBC to the Java CLASSPATH:

  1. Compile your application:

  1. Execute the Java class:

This page is: Copyright © 2026 MariaDB. All rights reserved.

Transactions with MariaDB Connector/R2DBC (Native API)

The MariaDB Connector/R2DBC native API requires manual subscription for beginTransaction, commitTransaction, and rollbackTransaction; Spring Data R2DBC provides managed transactions.

Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes R2DBC more scalable than Java's standard JDBC API.

Transactions

By default, MariaDB Connector/R2DBC enables the auto-committing of transactions on all connections. When you issue a statement that modifies the table through the Connector, it automatically commits the transaction, making the change permanent on the database.

The native implementation of MariaDB Connector/R2DBC does not provide out-of-the-box support for reactive streams transactions unless user-managed transactions are subscribed to using Mono.from(Connection.beginTransaction()).block(), Mono.from(Connection.commitTransaction()).block(), and Mono.from(Connection.rollbackTransaction()).block() method calls.

To use Spring framework-managed reactive streams transactions from your Java code, use MariaDB Connector/R2DBC with Spring Data R2DBC.

This page is: Copyright © 2026 MariaDB. All rights reserved.

Setup for Connector/R2DBC Examples (Spring Data)

Set up the test database, contact table, and user account required by the MariaDB Connector/R2DBC Spring Data code examples in this documentation section.

Overview

The examples in this MariaDB Connector/R2DBC documentation depend on a database test and table contact.

Create the Schema

Create a test database if one does not exist with the CREATE DATABASE statement:

CREATE DATABASE IF NOT EXISTS test;

Create the User

  1. Create a user account to test connectivity with the CREATE USER statement:

CREATE USER 'connr2dbc_test'@'192.0.2.50'
   IDENTIFIED BY 'db_user_password';
  1. Ensure that the user account has privileges to access the tables with the GRANT statement:

This page is: Copyright © 2026 MariaDB. All rights reserved.

Efficient: R2DBC uses deferred execution and flow control to ensure its operations are performed efficiently.
  • Simple: R2DBC is designed to make common usage patterns simple to implement for developers.

  • Fast

    Yes

    Yes

    Efficient

    Yes

    Yes

    Executes SQL

    Yes

    Yes

    Integrates with Spring Framework

    No

    Yes

    Spring Data: DatabaseClient

    No

    Yes

    Spring Data: Repositories

    No

    Yes

    Spring Data: Object Mapping

    No

    Yes

    Spring Data: Transaction Management

    No

    Yes

    Supported Versions

    1.4

    Programming Language

    JAVA

    Programming Language Version

    Java 8+

    API

    R2DBC 0.9.1 , R2DBC 1.0.0

    Supports TLS

    Yes

    Supports Connection Pools

    Yes

    License

    Apache 2.0

    <dependency>
        <groupId>org.mariadb</groupId>
        <artifactId>r2dbc-mariadb</artifactId>
        <version>1.4.1</version>
    </dependency>

    Native R2DBC

    The native implementation of R2DBC can be used to connect using MariaDB Connector/R2DBC from within your Java application.

    Spring Data R2DBC

    Spring Data implementation of R2DBC allows you to connect using MariaDB Connector/R2DBC using the Spring Framework.

    Feature

    Native R2DBC

    Spring Data R2DBC

    Reactive

    Yes

    Yes

    Scalable

    Yes

    End-of-Life (EOL) Versions

    Maven artifacts

    Benefits of R2DBC

    Framework-Specific Documentation

    Resources

    Release Notes
    GitHub
    Download Connectors
    MariaDB Connector/R2DBC
    Download Connector/R2DBC 1.4.1

    Yes

    CREATE USER 'connr2dbc_test'@'192.0.2.50'
       IDENTIFIED BY 'db_user_password';
    GRANT ALL PRIVILEGES
       ON test.*
       TO 'connr2dbc_test'@'192.0.2.50';
    $ export CLASSPATH="/path/to/application:/path/to/r2dbc-mariadb-1.4.1.jar"
    $ javac App.java
    $ java App
    GRANT ALL PRIVILEGES
       ON test.*
       TO 'connr2dbc_test'@'192.0.2.50';

    Application Development with MariaDB/Connector/R2DBC (Spring Data)

    Spring Data R2DBC applications with MariaDB Connector/R2DBC require Maven, Entity classes for object mapping, and the spring-boot-starter-data-r2dbc dependency.

    Overview

    Development with MariaDB Connector/R2DBC (Spring) involves building (compiling), and running applications. An Entity class also needs to be created.

    Building Applications

    When using Maven to manage your Java builds, running build downloads and installs the relevant JAR dependencies and compiles your project:

    Build the package:

    $ mvn package

    Run the application:

    $ java -jar target/app.jar

    Code Example: Create an Entity

    Spring Data R2DBC supports object mapping, which allows Java objects to map to rows in the database. This feature can be used to persist objects in the database and read objects from the database.

    Before using object mapping, the entity class that models the database table must be defined. The entity class consists of fields matching the database table columns.

    For example, entity class is shown below for the test.contact table defined in the , which contains the id, first_name, last_name, and email columns:

    • The entity class must have the same name as the database table it models.

    • For the test.contact table, the entity class is called Contact.

    • The entity class must declare an identifier (i.e., primary key) field by annotating the field declaration or its getter method declaration with @Id.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Install MariaDB Connector/R2DBC (Spring Data)

    Install MariaDB Connector/R2DBC with Spring Data via Maven using spring-boot-starter-data-r2dbc; Spring Boot 3.0 and later manage the r2dbc-mariadb connector version automatically.

    Overview

    Spring Data R2DBC and MariaDB Connector/R2DBC are usually installed using Maven.

    It should also be possible to install Spring Data R2DBC and MariaDB Connector/R2DBC by downloading the JAR files. Because Spring Data R2DBC has many dependencies we recommend using Maven, so that dependencies can be resolved by Maven.

    Install MariaDB Connector/R2DBC via Maven

    1. To install Spring module for R2DBC, add the spring-boot-starter-data-r2dbc package dependency to your application's pom.xml file:

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-r2dbc</artifactId>
       <version>3.3.5</version>
    </dependency>
    1. Since spring boot 3.0, the MariaDB connector is defined as a possible dependency. So setting dependency just needs:

    1. For spring boot before 3.0, a connector compatible with the R2DBC 0.9.1 spec needs to be set in place of org.mariadb:r2dbc-mariadb (be careful not to have any org.mariadb:r2dbc-mariadb dependency set):

    1. To build your application, run Maven:

    During the build process, Maven downloads and installs MariaDB Connector/R2DBC and other dependencies from the relevant repositories.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Install MariaDB Connector/R2DBC

    Install MariaDB Connector/R2DBC via Maven by adding the r2dbc-mariadb dependency to pom.xml, or manually by downloading the JAR and adding it to the Java CLASSPATH alongside r2dbc-pool.

    MariaDB Connector/R2DBC is usually installed using Maven or by manually downloading the JAR file. The Maven build process connects to repositories to download and install dependencies, including MariaDB Connector/R2DBC and any other specified dependencies your application may require.

    When downloading MariaDB Connector/R2DBC, you must manually add dependencies to your Java CLASSPATH.

    Install MariaDB Connector/R2DBC via JAR

    To download the JAR file manually: Go to the MariaDB Connector/R2DBC download page

    1. Ensure the "Product" dropdown reads "R2DBC connector."

    2. In the "Version" dropdown, select the version you want to download.

    3. Click the "Download" button to download the JAR file.

    4. When the JAR file finishes downloading, place it into the relevant directory on your system.

    5. If you plan to use , download the JAR file for the , and place it into the relevant directory on your system.

    6. Confirm that the relevant JAR files are in your Java CLASSPATH.

    1. Add the r2dbc-mariadb package as a dependency for your application to your application's pom.xml file. To install the latest Connector/R2DBC release, add the following:

    1. If you plan to use , add the as an additional dependency for your application to your application's pom.xml file.

    1. Run Maven to build your application:

    During the build process, Maven downloads and installs MariaDB Connector/R2DBC and other dependencies from the relevant repositories. After the build process completes and the MariaDB Connector/R2DBC has been installed, it can be used in a Java application.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Connect with MariaDB Connector/R2DBC (Native API)

    Connecting to MariaDB with the native R2DBC API uses MariadbConnectionConfiguration and MariadbConnectionFactory to create and manage reactive client connections via io.r2dbc.spi.Connection.

    Java developers can use MariaDB Connector/R2DBC to establish client connections with MariaDB database products.

    Connections are created, used, and managed using the following Java classes:

    Class
    Description

    Using the Spring Data Framework with MariaDB Connector/R2DBC

    Learn to integrate MariaDB Connector/R2DBC with Spring Data Framework. This guide covers reactive, non-blocking data access using Spring Data R2DBC for efficient and modern Java applications.

    Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes it more scalable than Java's standard JDBC API. MariaDB Connector/R2DBC can be used with the very popular Spring Data framework, which can provide support for repositories, object mapping, and transaction management.

    This page discusses how to use MariaDB Connector/R2DBC with the Spring Data framework.

    For information on how to use MariaDB Connector/R2DBC with the native R2DBC API, refer to, .

    allows MariaDB Connector/R2DBC to be used with the popular framework, which is part of the larger .

    Spring Data R2DBC is currently in incubation, so it is not yet included with the main Spring Data modules.

    R2DBC Code Example (Native API)

    Complete Java code example using the MariaDB Connector/R2DBC native API to query a MariaDB table with MariadbConnectionFactory and reactive Flux result handling.

    The following example uses the native R2DBC API to select data from the table defined in . Complete information on using is available.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    org.mariadb.r2dbc.MariadbConnectionConfiguration

    Configures client connections for the connection factory.

    io.r2dbc.spi.Connection

    Implements the R2DBC client connection.

    The following code example connects to a server using the database and user account created in Setup for Examples:

    • The connection must be configured for either host/port or socket, but it cannot be configured for both host/port and socket.

    • For maximum portability, connections should be used synchronously.

    • Objects created by a connection are only valid as long as the connection remains open.

    • When configuring a connection, R2DBC applications should use the appropriate methods such as beginTransaction(), setAutoCommit(boolean), and setTransactionIsolationLevel(IsolationLevel) to change transaction properties. Applications should not execute SQL commands directly to change the connection configuration when a R2DBC method is available.

    • New connections are by default created in auto-commit mode.

    • When you are done with a connection, close it to free resources. Close the connection using the close() method.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    org.mariadb.r2dbc.MariadbConnectionFactory

    Code Example: Connect

    Creates client connections.

    // Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import io.r2dbc.spi.Connection;
    
    // Main Application Class
    public class App {
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static Connection conn;
    
       // Main Process
       public static void main(String[] args) {
          //Initialize Connection Factory
          initConnectionFactory();
    
         //Initialize a Connection
         conn = connFactory.create().block();
    
          // Use the connection
          //conn.
       }
    
       public static void initConnectionFactory() {
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
          }
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Issue encountered while getting connection");
             e.printStackTrace();
          }
       }
    }
    Spring Data R2DBC supports many features from the Spring Data framework:
    Spring Data Feature
    Supported

    DatabaseClient

    Yes

    Repositories

    Yes

    Object Mapping

    Yes

    Application Development with MariaDB/Connector/R2DBC (Spring Data)

    Spring Data R2DBC applications with MariaDB Connector/R2DBC require Maven, Entity classes for object mapping, and the spring-boot-starter-data-r2dbc dependency.

    Batch Operations with MariaDB Connector/R2DBC (Spring Data)

    Spring Data R2DBC batch with MariaDB Connector/R2DBC loops over statements via DatabaseClient.execute, replacing the native io.r2dbc.spi.Batch class unavailable in this framework.

    Connect with MariaDB Connector/R2DBC (Spring Data)

    MariaDB Connector/R2DBC Spring Data wraps MariadbConnectionFactory in DatabaseClient, providing a higher-level reactive interface for executing queries against MariaDB.

    DDL with MariaDB Connector/R2DBC (Spring Data)

    Spring Data R2DBC DDL with MariaDB Connector/R2DBC uses DatabaseClient.execute to run schema statements including CREATE TABLE and ALTER TABLE within the Spring reactive framework.

    DML with MariaDB Connector/R2DBC (Spring Data)

    Spring Data R2DBC DML with MariaDB Connector/R2DBC uses DatabaseClient methods execute, select, insert, update, and delete for reactive INSERT, SELECT, UPDATE, and DELETE.

    Install MariaDB Connector/R2DBC (Spring Data)

    Install MariaDB Connector/R2DBC with Spring Data via Maven using spring-boot-starter-data-r2dbc; Spring Boot 3.0 and later manage the r2dbc-mariadb connector version automatically.

    R2DBC Code Example (Spring Data)

    Complete Java code example using MariaDB Connector/R2DBC with Spring Data R2DBC to query a MariaDB table via DatabaseClient and reactive StepVerifier result assertions.

    Repositories with MariaDB Connector/R2DBC (Spring Data)

    Spring Data repositories with MariaDB Connector/R2DBC use ReactiveCrudRepository and JavaConfig to implement reactive CRUD, with ApplicationConfig, Entity, Repository, and Service classes.

    Setup for Connector/R2DBC Examples (Spring Data)

    Set up the test database, contact table, and user account required by the MariaDB Connector/R2DBC Spring Data code examples in this documentation section.

    Transactions with MariaDB Connector/R2DBC (Spring Data)

    Spring Data R2DBC transactions with MariaDB Connector/R2DBC use R2dbcTransactionManager and TransactionalOperator for framework-managed reactive commit and rollback.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Overview

    Spring Data R2DBC

    Using the native API of MariaDB Connector/R2DBC
    Spring Data R2DBC
    Spring Data
    Spring Framework

    In This Section

    Resources

    // Imports the @Id annotation type, which demarcates an identifier.
    import org.springframework.data.annotation.Id;
    
    // This is an Entity class
    // It has the same name as the text.contact table
    public class Contact {
    
          // The class members correspond to columns
          // in the test.contact table
          private int id;
          private String first_name;
          private String last_name;
          private String email;
    
          // Constructor
          public Contact(int id, String first_name, String last_name, String email) {
             this.id = id;
             this.first_name = first_name;
             this.last_name = last_name;
             this.email = email;
          }
    
          // The @Id annotation indicates that this field
          // is the primary key column
          @Id
          public int getId() {
             return id;
          }
    
          public String getFirst_name() {
             return first_name;
          }
    
          public String getLast_name() {
             return last_name;
          }
    
          public String getEmail() {
             return email;
          }
    
          @Override
          public String toString() {
             return "Contact [id=" + id + ", first_name=" + first_name + ", last_name=" + last_name + ", email=" + email + "]";
          }
       }
    Setup for Examples
    <dependency>
        <groupId>org.mariadb</groupId>
        <artifactId>r2dbc-mariadb</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mariadb</groupId>
        <artifactId>r2dbc-mariadb-0.9.1-spec</artifactId>
        <version>1.4.1</version>
    </dependency>
    $ mvn package
    <dependency>
       <groupId>org.mariadb</groupId>
       <artifactId>r2dbc-mariadb</artifactId>
       <version>1.4.1</version>
    </dependency>
    <dependency>
        <groupId>io.r2dbc</groupId>
        <artifactId>r2dbc-pool</artifactId>
        <version>1.0.2.RELEASE</version>
    </dependency>
    $ mvn package

    Install MariaDB Connector/R2DBC via Maven

    Connection Pools
    r2dbc-pool package
    Connection Pools
    r2dbc-pool package
    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import io.r2dbc.spi.Connection;
    import io.r2dbc.spi.Statement;
    import io.r2dbc.spi.Result;
    import io.r2dbc.spi.Row;
    import io.r2dbc.spi.RowMetadata;
    import reactor.core.publisher.Flux;
    
    public class App {
    
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static Connection conn;
    
       public static void main(String[] argv) {
    
          // Initialize Connection
          initConnection();
    
          // Print contacts
          printContactList();
    
          // Close Connection
          conn.close();
       }
    
       public static void initConnection() {
    
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
             // Instantiate a Connection
             conn = connFactory.create().block();
          }
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Issue encountered while getting connection");
             e.printStackTrace();
          }
       }
    
       public static void printContactList() {
    
          try {
             // Initialize Statement
             Statement stmnt = conn.createStatement(
                "SELECT first_name, last_name, email FROM test.contacts");
    
             // Execute Statement and Iterate over the Result-set
             for (String contact_entry : Flux.from(stmnt.execute()).flatMap( res ->
                res.map( (row, metadata) -> {
    
                return String.format( "- %s %s <%s>",
                   // Get First Name
                   row.get(0, String.class),
    
                   //  Get Last Name
                   row.get(1, String.class),
    
                   //Get Email
                   row.get(2, String.class));
             })).toIterable()) {
    
                System.out.println(contact_entry);
             }
          }
          // Catch Exception
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Encountered issue querying contact list");
             e.printStackTrace();
          }
       }
    }
    * John Smith <john.smith@example.com>
    * Jon Smith <jon.smith@example.com>

    Overview

    Example output:

    Setup for Examples
    Connector/R2DBC natively

    R2DBC Code Example (Spring Data)

    Complete Java code example using MariaDB Connector/R2DBC with Spring Data R2DBC to query a MariaDB table via DatabaseClient and reactive StepVerifier result assertions.

    Overview

    The following example uses the Spring Data R2DBC framework to select data from the table defined in Setup for Example. Complete information on using Connector/R2DBC with the Spring Data framework is available.

    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import org.springframework.data.r2dbc.core.DatabaseClient;
    import reactor.test.StepVerifier;
    
    // Main Application Class
    public class App {
      // Connection Configuration
      private static MariadbConnectionConfiguration conf;
      private static MariadbConnectionFactory connFactory;
    
      private static DatabaseClient client;
    
      // Main Process
      public static void main(String[] args) {
         try {
            conf = MariadbConnectionConfiguration.builder()
                 !SILO=ent!
                 .host("192.0.2.1").port(3306)
                 !SILO=sky!
                 .host("example.skysql.net").port(5509)
                 !END-SILO!
                 .username("db_user").password("db_user_password")
                 .database("test").build();
    
            // Instantiate a Connection Factory
            connFactory = new MariadbConnectionFactory(conf);
    
            // Instantiate a Database Client
            client = DatabaseClient.create(connFactory);
    
            // Select all rows
            client.select()
               .from(Contact.class)
               .fetch().all()
               .doOnNext(it -> System.out.println(it))
               .as(StepVerifier::create)
               .expectNextCount(3)
               .verifyComplete();
    
            // Select the first row
            client.select()
               .from(Contact.class)
               .fetch().first()
               .doOnNext(it -> System.out.println(it))
               .as(StepVerifier::create)
               .expectNextCount(1)
               .verifyComplete();
    
            // Select all rows with explicit query
            client.execute("SELECT id, first_name,last_name,email FROM contact")
               .as(Contact.class)
               .filter(s -> s.fetchSize(25))
               .fetch().all()
               .doOnNext(it -> System.out.println(it))
               .as(StepVerifier::create)
               .expectNextCount(3)
               .verifyComplete();
    
            // Select single column
            client.execute("SELECT first_name FROM contact")
               .map((row, rowMetadata) -> row.get("first_name", String.class))
               .all()
               .doOnNext(it -> System.out.println(it))
               .as(StepVerifier::create)
               .expectNextCount(3)
               .verifyComplete();
    
         } catch (IllegalArgumentException e) {
            e.printStackTrace();
         } catch (io.r2dbc.spi.R2dbcNonTransientResourceException e) {
            e.printStackTrace();
         } finally {
         }
      }
    }

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Connect with MariaDB Connector/R2DBC (Spring Data)

    MariaDB Connector/R2DBC Spring Data wraps MariadbConnectionFactory in DatabaseClient, providing a higher-level reactive interface for executing queries against MariaDB.

    Java developers can use MariaDB Connector/R2DBC to establish client connections with MariaDB database products.

    Connections are created, used, and managed using several classes:

    Class
    Description

    Batch Operations with MariaDB Connector/R2DBC (Spring Data)

    Spring Data R2DBC batch with MariaDB Connector/R2DBC loops over statements via DatabaseClient.execute, replacing the native io.r2dbc.spi.Batch class unavailable in this framework.

    Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes it more scalable than Java's standard JDBC API. MariaDB Connector/R2DBC can be used with the very popular Spring Data R2DBC framework, which can provide support for repositories, object mapping, and transaction management.

    Spring Data R2DBC has no built-in support for batch operations as the native API does with the io.r2dbc.spi.Batch class. With Spring Data R2DBC, batch operations can be performed by looping over a List of SQL statements and invoking DatabaseClient.execute(String sql) for each SQL statement.

    DML (Data Manipulation Language) refers to all SQL-data statements in the SQL standard (ISO/IEC 9075-2:2016), for example, , , , , and .

    DDL (Data Definition Language) refers to all SQL-schema statements in the SQL standard (ISO/IEC 9075-2:2016), for example , , , , and

    spinner
    spinner
    spinner
    spinner
    spinner
    spinner
    spinner
    spinner
    spinner

    Transaction Management

    Yes

    spinner
    spinner

    org.mariadb.r2dbc.MariadbConnectionConfiguration

    Configures client connections for the connection factory.

    io.r2dbc.spi.Connection

    Implements the R2DBC client connection.

    org.springframework.data.r2dbc.core.DatabaseClient

    Creates a higher level, reactive client for Reactive Streams.

    The following example shows how to use the DatabaseClient class to connect and execute queries:

    After running the application App, verify that the table has been created:

    A DatabaseClient uses the underlying ConnectionFactory to get and release connections for each database operation without affinity to a particular connection across the multiple operations. When using Spring's R2DBC layer, a custom connection pool could be configured using an implementation provided by a third party.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    org.mariadb.r2dbc.MariadbConnectionFactory

    Overview

    Creating a Database Client

    Creates client connections.

    Code Example: Connect

    Connection Pools

    spinner
    // Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import org.springframework.data.r2dbc.core.DatabaseClient;
    
    import reactor.test.StepVerifier;
    
    // Main Application Class
    public class App {
    
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static DatabaseClient client;
    
       // Main Process
       public static void main(String[] args) {
    
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
             // Instantiate a Database Client
             client = DatabaseClient.create(connFactory);
    
             // Create a Database Table
    
             client.execute("CREATE TABLE IF NOT EXISTS test.contact" + "(id INT PRIMARY KEY AUTO_INCREMENT,"
                   + "first_name VARCHAR(25)," + "last_name VARCHAR(25)," + "email VARCHAR(25)) ENGINE=InnoDB")
                   .fetch()
                   .rowsUpdated()
                   .as(StepVerifier::create)
                   .expectNextCount(1)
                   .verifyComplete();
    
          } catch (IllegalArgumentException e) {
             e.printStackTrace();
          } catch (io.r2dbc.spi.R2dbcNonTransientResourceException e) {
             e.printStackTrace();
          } finally {
    
          }
       }
    }
    SHOW TABLES;
    +----------------+
    | Tables_in_test |
    +----------------+
    | contact        |
    +----------------+
    DESCRIBE contact;
    +------------+-------------+------+-----+--------------------------+
    | Field      | Type        | Null | Key | Default  | Extra         |
    +------------+-------------+------+-----+----------+---------------+
    | id         | int(11)     | NO   | PRI | NULL     | auto_increment|
    | first_Name | varchar(25) | YES  |     | NULL     |               |
    | last_Name  | varchar(25) | YES  |     | NULL     |               |
    | email      | varchar(25) | YES  |     | NULL     |               |
    +------------+-------------+------+-----+----------+---------------+
    .

    The following example shows how to use a batch operation to duplicate the example table created in Setup for Examples:

    After running the application App, confirm the table has been created:

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Overview

    Batch Operations

    Code Example: Batching DML and DDL

    //Module Imports
    import java.util.Arrays;
    import java.util.List;
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import org.springframework.data.r2dbc.core.DatabaseClient;
    import reactor.test.StepVerifier;
    
    // Main Application Class
    public class App {
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static DatabaseClient client;
    
       // Main Process
       public static void main(String[] args) {
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
             // Instantiate a Database Client
             client = DatabaseClient.create(connFactory);
    
             // Create a list or batch of SQL statements
             List<String> batch = Arrays.asList(
                   "CREATE DATABASE IF NOT EXISTS test;",
                   "CREATE TABLE IF NOT EXISTS test.contact_copy(id INT PRIMARY KEY AUTO_INCREMENT,first_name VARCHAR(50),last_name VARCHAR(50),email VARCHAR(250)) ENGINE=InnoDB;",
                   "INSERT INTO test.contact_copy SELECT * FROM test.contact;");
    
             //Run the batch of SQL statements
             batch.forEach(stmt -> client.execute(stmt)
                   .fetch()
                   .rowsUpdated()
                   .as(StepVerifier::create)
                   .expectNextCount(1)
                   .verifyComplete());
    
          } catch (IllegalArgumentException e) {
             e.printStackTrace();
          } catch (io.r2dbc.spi.R2dbcNonTransientResourceException e) {
             e.printStackTrace();
          } finally {
    
          }
       }
    }
    USE test;
    SHOW TABLES;
    +----------------+
    | Tables_in_test |
    +----------------+
    | contact        |
    | contact_copy   |
    +----------------+
    DESCRIBE contact_copy;
    +------------+-------------+------+-----+--------------------------+
    | Field      | Type        | Null | Key | Default  | Extra         |
    +------------+-------------+------+-----+----------+---------------+
    | id         | int(11)     | NO   | PRI | NULL     | auto_increment|
    | first_Name | varchar(25) | YES  |     | NULL     |               |
    | last_Name  | varchar(25) | YES  |     | NULL     |               |
    | email      | varchar(25) | YES  |     | NULL     |               |
    +------------+-------------+------+-----+----------+---------------+
    spinner

    Batch Operations with MariaDB Connector/R2DBC (Native API)

    Batch operations with the MariaDB Connector/R2DBC native API group multiple DML statements into a single io.r2dbc.spi.Batch to reduce per-statement network overhead.

    Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes R2DBC more scalable than Java's standard JDBC API.

    Batch Operations

    In cases where you need to execute multiple statements at a time, rather than a single statement, MariaDB Connector/R2DBC supports batch operations. With batch operations, you can group several statements together, which can improve performance.

    With R2DBC, batch operations are performed using the following class:

    Class
    Description

    DML (Data Manipulation Language) refers to all SQL-data statements in the SQL standard (ISO/IEC 9075-2:2016). The following example shows how to use a batch operation to add data to the example table created in and return data from the table (batching operations do not permit binding parameters):

    DDL (Data Definition Language) refers to all SQL-schema statements in the SQL standard (ISO/IEC 9075-2:2016). The following example shows how to use a batch operation to duplicate the example table created in (batching operations do not permit binding parameters):

    Confirm that the batch operation was properly executed by using to execute a statement against the table, and another against the newly created test.contact_copy table:

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Transactions with MariaDB Connector/R2DBC (Spring Data)

    Spring Data R2DBC transactions with MariaDB Connector/R2DBC use R2dbcTransactionManager and TransactionalOperator for framework-managed reactive commit and rollback.

    Overview

    Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes it more scalable than Java's standard JDBC API. MariaDB Connector/R2DBC can be used with the very popular Spring Data framework, which can provide support for repositories, object mapping, and transaction management.

    Transactions

    With Spring Data, transactions can be used by utilizing either the R2dbcTransactionManager class or the TransactionAwareConnectionFactoryProxy class. These two classes are mutually exclusive, so they cannot be used together.

    Code Example: Transaction Manager

    The following example shows how to perform some changes within a reactive streams transaction. The example uses the table created in Setup for Examples and the entity class created in Create the Entity class.

    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import org.springframework.data.r2dbc.connectionfactory.R2dbcTransactionManager;
    import org.springframework.data.r2dbc.core.DatabaseClient;
    import org.springframework.transaction.ReactiveTransactionManager;
    import org.springframework.transaction.reactive.TransactionalOperator;
    import reactor.test.StepVerifier;
    
    // Main Application Class
    public class App {
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static DatabaseClient client;
    
       // Main Process
       public static void main(String[] args) {
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
             ReactiveTransactionManager tm = new R2dbcTransactionManager(connFactory);
    
             TransactionalOperator operator = TransactionalOperator.create(tm);
    
             // Instantiate a Client
             client = DatabaseClient.create(connFactory);
    
             // Update a contact using the transactional operator
             Contact contact = new Contact(1, "Kai", "Devi", "kai.devi@example.com");
    
             client.update()
             .table(Contact.class)
             .using(contact)
             .then()
             .as(operator::transactional)
             .as(StepVerifier::create)
             .verifyComplete();
    
             // Update another contact using the transactional operator
             client.execute("UPDATE test.contact SET email = 'lee.wang@example.com' WHERE id = 2")
             .fetch().rowsUpdated()
             .then()
             .as(operator::transactional)
             .as(StepVerifier::create)
             .expectComplete()
             .verify();
    
          } catch (IllegalArgumentException e) {
             // ...
          } finally {
             // ...
          }
       }
    }
    • The ReactiveTransactionManager is the central interface in Spring's reactive transaction infrastructure. Applications can use this directly, but it is not primarily meant as an API. Typically, it is recommended that applications use ReactiveTransactionManager with either transactional operators or declarative transaction demarcation through AOP. This example uses it with transactional operators.

    • The R2dbcTransactionManager class is a ReactiveTransactionManager implementation for a single R2DBC ConnectionFactory. This class can be used in any environment with any R2DBC driver, as long as the setup uses a ConnectionFactory as its Connection factory mechanism. The R2dbcTransactionManager class assumes that a separate, independent Connection can be obtained even during an ongoing transaction.

    • The TransactionalOperator is the Operator interface that simplifies programmatic transaction demarcation and transaction exception handling. The central method is transactional, which supports transactional wrapping of functional sequences code. This operator handles the transaction lifecycle and possible exceptions such that neither the ReactiveTransactionCallback implementation nor the calling code needs to explicitly handle transactions.

    The following example shows how to use the TransactionAwareConnectionFactoryProxy class, which is a proxy for a target R2DBC ConnectionFactory, adding awareness of Spring-managed transactions.

    The main benefit of the proxy class is that it allows data access code to be used with either the plain R2DBC API or the DatabaseClient. The DatabaseClient gets transaction participation even without a proxy.

    • The DatabaseClient is configured with the proxy connection factory that is aware of Spring managed transactions.

    • The TransactionAwareConnectionFactoryProxy as a proxy must not be used when using the reactive streams transactions.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    spinner

    DDL with MariaDB Connector/R2DBC (Native API)

    DDL operations with the MariaDB Connector/R2DBC native API execute schema statements such as CREATE TABLE and ALTER TABLE reactively using io.r2dbc.spi.Statement and io.r2dbc.spi.Result.

    Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes R2DBC more scalable than Java's standard JDBC API.

    DDL (Data Definition Language) refers to all SQL-schema statements in the SQL standard (ISO/IEC 9075-2:2016).

    Some examples of DDL include , , , , and .

    With R2DBC, DDL statements are performed with the following classes:

    Class

    DDL with MariaDB Connector/R2DBC (Spring Data)

    Spring Data R2DBC DDL with MariaDB Connector/R2DBC uses DatabaseClient.execute to run schema statements including CREATE TABLE and ALTER TABLE within the Spring reactive framework.

    Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes it more scalable than Java's standard JDBC API. MariaDB Connector/R2DBC can be used with the very popular Spring Data framework, which can provide support for repositories, object mapping, and transaction management.

    DDL (Data Definition Language) refers to all SQL-schema statements in the SQL standard (ISO/IEC 9075-2:2016).

    Some examples of DDL include , , , , and .

    With Spring Data, DDL operations can be performed by invoking the following methods:

    Connection Pools with MariaDB Connector/R2DBC (Native API)

    The MariaDB Connector/R2DBC native API supports connection pooling via r2dbc-pool, holding reactive connections open for reuse and configuring them with ConnectionPoolConfiguration.

    Connection pools enable the reuse of database connections to minimize the performance overhead of connecting to the database and the churn of opening and closing connections.

    Connection pools hold connections open in a pool. When the process is done with the connection, it is returned to the pool rather than closed, allowing MariaDB Connector/R2DBC to acquire a connection as needed.

    Connection pools require . Refer to the page for more details.

    Connection pools are created, used, and managed using several classes:

    Class

    Code Example: Proxy

    spinner
    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import org.springframework.data.r2dbc.connectionfactory.TransactionAwareConnectionFactoryProxy;
    import org.springframework.data.r2dbc.core.DatabaseClient;
    import reactor.test.StepVerifier;
    
    // Main Application Class
    public class App {
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static DatabaseClient client;
    
       // Main Process
       public static void main(String[] args) {
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
             TransactionAwareConnectionFactoryProxy proxy = new TransactionAwareConnectionFactoryProxy(connFactory);
    
             // Instantiate a Client
             client = DatabaseClient.create(proxy);
    
             // Update Data
             Contact contact = new Contact(1, "Kai", "Devi", "kai.devi@example.com");
    
             client.update().table(Contact.class).using(contact).then().as(StepVerifier::create).verifyComplete();
    
             client.execute("UPDATE test.contact SET email = 'lee.wang@example.com' WHERE id = 2").fetch().rowsUpdated()
             .then().as(StepVerifier::create).expectComplete().verify();
    
          } catch (IllegalArgumentException e) {
             // ...
          } finally {
             // ...
          }
       }
    }
    Description

    io.r2dbc.spi.Statement

    Creates a statement to execute on the server.

    io.r2dbc.spi.Result

    Contains the result-set from the server.

    ALTER TABLE is a DDL (Data Definition Language) operation that makes changes to an existing table. The following example changes the example table created in Setup for Examples.

    Confirm the table was properly altered by using MariaDB Client to execute a DESC statement on the same table:

    The following example shows how to truncate the example table created in Setup for Examples.

    TRUNCATE is a DDL (Data Definition Language) operation that deletes all data from an existing table and resets the AUTO_INCREMENT column counter to 0:

    Confirm the table was properly truncated by using MariaDB Client to execute a SELECT statement on the same table:

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Overview

    DDL Operations

    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import io.r2dbc.spi.Connection;
    import reactor.core.publisher.Mono;
    
    //Main Application Class
    public class App {
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static Connection conn;
    
       // Main Process
       public static void main(String[] args) {
          // Initialize Connection Factory
          initConnectionFactory();
    
          // Alter Contacts Table
          alterContactsTable();
       }
    
       public static void initConnectionFactory() {
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
          }
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Issue encountered while creating  connection factory");
             e.printStackTrace();
          }
       }
    
       public static void alterContactsTable() {
          try {
             //Initialize a Connection
             conn = connFactory.create().block();
    
             //Create and run a Statement
             Mono.from(
                conn.createStatement("ALTER TABLE test.contact CHANGE COLUMN first_name f_name VARCHAR(25)").execute()
             ).subscribe();
          }
          // Catch Exception
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Issue altering contact table");
             e.printStackTrace();
          } finally {
             // Close Connection
             conn.close();
          }
       }
    }
    DESC test.contact;
    +-----------+-------------+------+-----+---------+----------------+
    | Field     | Type        | Null | Key | Default | Extra          |
    +-----------+-------------+------+-----+---------+----------------+
    | id        | int(11)     | NO   | PRI | NULL    | auto_increment |
    | f_name    | varchar(25) | YES  |     | NULL    |                |
    | last_name | varchar(25) | YES  |     | NULL    |                |
    | email     | varchar(25) | YES  |     | NULL    |                |
    +-----------+-------------+------+-----+---------+----------------+
    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import io.r2dbc.spi.Connection;
    import reactor.core.publisher.Mono;
    
    //Main Application Class
    public class App {
    
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static Connection conn;
    
       // Main Process
       public static void main(String[] args) {
          //Initialize Connection Factory
          initConnectionFactory();
    
          // Truncate table
          truncateTable();
       }
    
       public static void initConnectionFactory() {
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
          }
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Issue encountered while getting connection");
             e.printStackTrace();
          } finally {
             // ...
          }
       }
    
       public static void truncateTable() {
          try {
    
             //Initialize a Connection
             conn = connFactory.create().block();
    
             // Initialize and run a Statement
    
             Mono.from(
                conn.createStatement("TRUNCATE test.contact").execute()
             ).subscribe();
          }
          // Catch Exception
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Issue truncating contact table");
             e.printStackTrace();
          } finally {
             // Close Connection
             conn.close();
          }
       }
    }
    SELECT * FROM test.contact;
    Empty set (0.000 sec)

    Code Example: ALTER TABLE

    Code Example: TRUNCATE TABLE

    spinner
    Method
    Description

    DatabaseClient.execute(String sql)

    Execute any DDL statement.

    CREATE TABLE is a DDL (Data Definition Language) operation that creates a new table.

    Complete the Setup for Examples and Create the Entity class before using the example.

    The following example shows how to execute a CREATE TABLE statement:

    After running the application App, verify the table has been created:

    The following code example truncates the test.contact table created above.

    TRUNCATE is a DDL (Data Definition Language) operation that deletes all data from an existing table and resets the AUTO_INCREMENT column counter to 0:

    • A connection factory is used to create an instance of DatabaseClient to connect to the database.

    • The DROP and CREATE privileges are needed to truncate a table as TRUNCATE is a DDL statement that drops the table and creates a new table with the same table definition, in effect deleting all data.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Overview

    DDL Operations

    // Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import org.springframework.data.r2dbc.core.DatabaseClient;
    
    import reactor.test.StepVerifier;
    
    // Main Application Class
    public class App {
    
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static DatabaseClient client;
    
       // Main Process
       public static void main(String[] args) {
    
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
             // Instantiate a Database Client
             client = DatabaseClient.create(connFactory);
    
             // Create a Database Table
    
             client.execute("CREATE OR REPLACE TABLE test.contact" + "(id INT PRIMARY KEY AUTO_INCREMENT,"
                   + "first_name VARCHAR(25)," + "last_name VARCHAR(25)," + "email VARCHAR(25)) ENGINE=InnoDB")
                   .fetch()
                   .rowsUpdated()
                   .as(StepVerifier::create)
                   .expectNextCount(1)
                   .verifyComplete();
    
          } catch (IllegalArgumentException e) {
             e.printStackTrace();
          } catch (io.r2dbc.spi.R2dbcNonTransientResourceException e) {
             e.printStackTrace();
          } finally {
    
          }
       }
    }
    SHOW TABLES;
    +----------------+
    | Tables_in_test |
    +----------------+
    | contact        |
    +----------------+
    DESC contact;
    +------------+-------------+------+-----+--------------------------+
    | Field      | Type        | Null | Key | Default  | Extra         |
    +------------+-------------+------+-----+----------+---------------+
    | id         | int(11)     | NO   | PRI | NULL     | auto_increment|
    | first_Name | varchar(25) | YES  |     | NULL     |               |
    | last_Name  | varchar(25) | YES  |     | NULL     |               |
    | email      | varchar(25) | YES  |     | NULL     |               |
    +------------+-------------+------+-----+----------+---------------+
    // Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import org.springframework.data.r2dbc.core.DatabaseClient;
    
    import reactor.test.StepVerifier;
    
    // Main Application Class
    public class App {
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static DatabaseClient client;
    
       // Main Process
       public static void main(String[] args) {
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
             // Instantiate a Database Client
             client = DatabaseClient.create(connFactory);
    
             // Truncate Database Table
    
             client.execute("TRUNCATE TABLE test.contact").fetch()
                   .rowsUpdated().as(StepVerifier::create).expectNextCount(1).verifyComplete();
          } catch (IllegalArgumentException e) {
             e.printStackTrace();
          } catch (io.r2dbc.spi.R2dbcNonTransientResourceException e) {
             e.printStackTrace();
          } finally {
          }
       }
    
    }

    Code Example: CREATE TABLE

    Code Example: TRUNCATE TABLE

    spinner
    Description

    org.mariadb.r2dbc.MariadbConnectionFactory

    Creates client connections.

    org.mariadb.r2dbc.MariadbConnectionConfiguration

    Configures client connections for the connection factory.

    io.r2dbc.pool.ConnectionPoolConfiguration

    Configures the connection pool.

    io.r2dbc.pool.ConnectionPool

    Implements the R2DBC connection pool.

    io.r2dbc.spi.Connection

    The following code example initializes a connection pool:

    • The maxIdleTime(Duration maxIdleTime) method sets the maximum idle time. The value must not be null and must not be negative, though it could be 0. If the value is invalid, the method throws an IllegalArgumentException, which is handled in the catch block. The default value is 30 minutes.

    • The maxSize(int maxSize) method sets the maximum connection pool size. The value must be greater than 0. If the value is invalid, the method throws an IllegalArgumentException, which is handled in the catch block. The default value is 10.

    When using a connection pool, you can retrieve connections from the connection pool using the create() method.

    The following code example retrieves a connection from a connection pool. The code to initialize the connection pool is in Initialize Connection Pools:

    When you are done with a connection retrieved from the pool, close it using the close() method:

    Connections retrieved from connection pools are returned to the pool when closed. The pool keeps a certain pre-configured number of connections available for use. If a connection is retrieved with the create() method again, a connection from the pool is returned.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Connection Pool Classes

    r2dbc-pool
    Installation
    // Module Imports
    import java.time.Duration;
    import io.r2dbc.pool.ConnectionPool;
    import io.r2dbc.pool.ConnectionPoolConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    
    public class App {
    
       // Attributes
       private MariadbConnectionFactory connFactory;
       private ConnectionPool pool;
    
       // Main Process
       public static void main(String[] args) {
    
          App  app = new App();
          app.createConnectionPool();
       }
    
       public void createConnectionPool() {
    
          try {
             // Configure and Create Connection Factory
             MariadbConnectionConfiguration factoryConfig = MariadbConnectionConfiguration
                .builder().host("192.0.2.1").port(3306)
                .username("db_user").password("db_user_password")
                .database("test").build();
    
             this.connFactory = new MariadbConnectionFactory(factoryConfig);
    
             // Configure Connection Pool
             ConnectionPoolConfiguration poolConfig = ConnectionPoolConfiguration
                .builder(connFactory)
                .maxIdleTime(Duration.ofMillis(1000))
                .maxSize(20)
                .build();
    
             this.pool = new ConnectionPool(poolConfig);
          }
          // Catch Exception
           catch (IllegalArgumentException e) {
             System.err.println("Issue creating connection pool");
             e.printStackTrace();
          } finally {
             // Close Connection
             pool.close();
          }
       }
    }
    // Module Imports
    import java.time.Duration;
    import io.r2dbc.pool.ConnectionPool;
    import io.r2dbc.pool.ConnectionPoolConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import io.r2dbc.spi.Connection;
    
    public class App {
    
       // Attributes
       private MariadbConnectionFactory connFactory;
       private static ConnectionPool pool;
       private Connection conn;
    
       // Main Process
       public static void main(String[] args) {
    
         App app = new App();
          app.createConnectionPool();
          app.setConnection(pool);
       }
    
       public void createConnectionPool() {
    
          try {
             // Configure and Create Connection Factory
             MariadbConnectionConfiguration factoryConfig = MariadbConnectionConfiguration
                .builder().host("192.0.2.1").port(3306)
                .username("db_user").password("db_user_password")
                .database("test").build();
    
             this.connFactory = new MariadbConnectionFactory(factoryConfig);
    
             // Configure Connection Pool
             ConnectionPoolConfiguration poolConfig = ConnectionPoolConfiguration
                .builder(connFactory)
                .maxIdleTime(Duration.ofMillis(1000))
                .maxSize(20)
                .build();
    
             this.pool = new ConnectionPool(poolConfig);
          }
          // Catch Exception
           catch (IllegalArgumentException e) {
             System.err.println("Issue creating connection pool");
             e.printStackTrace();
          }
       }
    
       public void setConnection(ConnectionPool pool) {
    
          // Set Connection
          this.conn = pool.create().block();
          //Use Connection
          //...
       }
    }
    // Return Connection to the Pool
    conn.close();

    Code Example: Initialize Connection Pool

    Code Example: Retrieve Connections

    Code Example: Close Connection

    spinner

    io.r2dbc.spi.Batch

    Executes batch operations.

    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import io.r2dbc.spi.Batch;
    import io.r2dbc.spi.Connection;
    import reactor.core.publisher.Flux;
    
    //Main Application Class
    public class App {
         // Connection Configuration
         private static MariadbConnectionConfiguration conf;
         private static MariadbConnectionFactory connFactory;
         private static Connection conn;
    
         // Main Process
         public static void main(String[] args) {
             //Initialize Connection Factory
             initConnectionFactory();
    
             // Add and Select Contacts in a batch operation
             addAndSelectContacts();
         }
    
         public static void initConnectionFactory() {
             try {
                 // Configure the Connection
                 conf = MariadbConnectionConfiguration.builder()
                      .host("192.0.2.1").port(3306)
                      .username("db_user").password("db_user_password")
                      .database("test").build();
                 // Instantiate a Connection Factory
                 connFactory = new MariadbConnectionFactory(conf);
    
             } catch (java.lang.IllegalArgumentException e) {
                 System.err.println("Issue encountered while getting connection");
                 e.printStackTrace();
             }
         }
    
         public static void addAndSelectContacts() {
             try {
                 //Initialize a Connection
                 conn = connFactory.create().block();
                 //Create a Batch Object
                 Batch batch = conn.createBatch();
                 batch = batch.add("INSERT INTO test.contact (" + "first_name, last_name, email)  VALUES" + "('Kai', 'Devi', 'kai.devi@example.com'), "
                              + "('Lee', 'Wang', 'lee.wang@example.com'), " + "('Dani', 'Smith', 'dani.smith@example.com')").add("SELECT * FROM test.contact");
    
                 for (String contact_entry : Flux.from(batch.execute()).flatMap( res -> res.map( (row, metadata) -> {
                         return String.format("- %s %s <%s>",
                             row.get(1, String.class), // Get First Name
                             row.get(2, String.class), // Get Last Name
                             row.get(3, String.class)); // Get Email
                         })).toIterable()) {
                     System.out.println(contact_entry);
                 }
             }
             // Catch Exception
             catch (IllegalArgumentException e) {
                 System.err.println("Issue running operation");
                 e.printStackTrace();
             } finally {// Close Connection
                 conn.close();
             }
         }
     }
    - Kai Devi <kai.devi@example.com>
    - Lee Wang <lee.wang@example.com>
    - Dani Smith <dani.smith@example.com>
    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import io.r2dbc.spi.Batch;
    import io.r2dbc.spi.Connection;
    import reactor.core.publisher.Mono;
    
    //Main Application Class
    public class App {
    
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static Connection conn;
    
      // Main Process
       public static void main(String[] args) {
    
          //Initialize Connection Factory
          initConnectionFactory();
    
          // Initialize the schema
          initializeSchema();
    
       }
    
       public static void initConnectionFactory() {
    
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
          }
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Issue encountered while getting connection");
             e.printStackTrace();
          }
       }
    
       public static void initializeSchema() {
    
          try {
             //Initialize a Connection
             conn = connFactory.create().block();
    
             //Create a Batch Object
             Batch batch = conn.createBatch();
             batch = batch.add("CREATE DATABASE IF NOT EXISTS test")
                   .add("CREATE TABLE IF NOT EXISTS " +
                        "test.contact_copy (" +
                        "id INT PRIMARY KEY AUTO_INCREMENT," +
                         "first_name VARCHAR(50)," +
                         "last_name VARCHAR(50)," +
                         "email VARCHAR(250)" +
                         ") ENGINE=InnoDB")
                   .add("INSERT INTO test.contact_copy SELECT * FROM test.contact");
             Mono.from(batch.execute()).subscribe();
          }
          // Catch Exception
          catch (IllegalArgumentException e) {
             System.err.println("Issue running operation");
             e.printStackTrace();
          }finally { // Close Connection
              conn.close();
          }
       }
    }
    SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE
       FROM information_schema.TABLES
       WHERE TABLE_SCHEMA='test'
       AND TABLE_NAME='contact_copy';
    +--------------+--------------+--------+
    | TABLE_SCHEMA |  TABLE_NAME  | ENGINE |
    +--------------+--------------+--------+
    | test         | contact_copy | InnoDB |
    +--------------+--------------+--------+
    SELECT * FROM contact_copy;
    +----+------------+-----------+------------------------+
    | id | first_name | last_name | email                  |
    +----+------------+-----------+------------------------+
    | 1  | Kai        | Devi      | kai.devi@example.com   |
    | 2  | Lee        | Wang      | lee.wang@example.com   |
    | 3  | Dani       | Smith     | dani.smith@example.com |
    +----+------------+-----------+------------------------+

    Code Example: Batching DML

    Example Output:

    Code Example: Batching DDL

    Setup for Examples
    Setup for Examples
    spinner

    DML with MariaDB Connector/R2DBC (Native API)

    DML with the MariaDB Connector/R2DBC native API executes INSERT, UPDATE, DELETE, and SELECT reactively using io.r2dbc.spi.Statement, Result, Row, and RowMetadata classes.

    Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes R2DBC more scalable than Java's standard JDBC API.

    DML Operations

    DML (Data Manipulation Language) refers to all SQL-data statements in the SQL standard (ISO/IEC 9075-2:2016), for example: , , , , and .

    With R2DBC, DML operations are performed with the following classes:

    Class
    Description

    The following example shows how to insert data into the example table created in :

    The bind (int index, Object value) method binds non-null values to indexed parameters. The index is an integer that starts at 0. If the value is null, the method throws an IllegalArgumentException; if the index is out of range, it throws an IndexOutOfBoundsException.

    Alternatively, the bind (String name, Object value) method could be used to bind a non-null value to a named parameter.

    The execute() method executes the statement and returns the results as a Publisher<? extends Result> instance.

    Result instances must be fully consumed to ensure full execution of the corresponding Statement instance.

    Confirm the data was properly inserted by using MariaDB Client to execute a SELECT statement:

    SELECT is a DML (Data Manipulation Language) operation that reads the data from a table. The following example shows how to select data from the example table created in :

    • The Flux must be fully consumed to retrieve results, for which the method call sequence Flux.from(stmnt.execute()).flatMap(...) is used.

    • Results can be consumed only once by either consuming getRowsUpdated() or map(BiFunction) method in the Result class.

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    DML with MariaDB Connector/R2DBC (Spring Data)

    Spring Data R2DBC DML with MariaDB Connector/R2DBC uses DatabaseClient methods execute, select, insert, update, and delete for reactive INSERT, SELECT, UPDATE, and DELETE.

    Overview

    Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes it more scalable than Java's standard JDBC API. MariaDB Connector/R2DBC can be used with the very popular Spring Data framework, which can provide support for repositories, object mapping, and transaction management.

    DML Operations

    DML (Data Manipulation Language) refers to all SQL-data statements in the SQL standard (ISO/IEC 9075-2:2016), for example, , , , , and .

    With Spring Data, DML operations can be performed by invoking the following methods:

    Method
    Description

    , , and are DML (Data Manipulation Language) operations that modify the data in a table.

    The following example shows how to insert data into the example table created in .

    To update or delete data, replace the INSERT statement in the code example with an UPDATE, or DELETE statement:

    • To update or delete data, use the update() or delete() methods, instead of the insert() method.

    • To execute a specific DML statement, use the execute() method.

    Confirm the data was properly inserted by using MariaDB Client to execute a SELECT statement.

    Example output:

    SELECT is a DML (Data Manipulation Language) operation that reads the data from a table.

    The following example shows how to select data from the example table created in :

    Example output:

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    MariaDB Connector/R2DBC Connection Parameters

    MariaDB Connector/R2DBC connection parameters cover SSL mode, authentication plugins, autocommit, transaction replay, timezone handling, and prepared statement options.

    Java developers can use MariaDB Connector/R2DBC to establish client connections with MariaDB database products.

    MariaDB Connector/R2DBC supports several connection parameters:

    Parameter Name
    Description
    Type
    Default Value

    Implements the R2DBC client connection.

    Result object maintains a consumption state that may be backed by a cursor pointing to its current row of data. A Result allows read-only and forward-only consumption of statement results. Thus, you can consume either getRowsUpdated() or map(BiFunction) through it only once and only from the first row to the last row.
  • The sample application makes use of the map(BiFunction<Row, RowMetadata, ? extends T> mappingFunction) method.

  • The map method returns a mapping of the rows that are the results of a query against a database. It may be empty if the query did not return any rows. A Row can be only considered valid within a BiFunction mapping function callback. The mapping Function BiFunction maps a Row and RowMetadata to a value. It throws an IllegalArgumentException if mappingFunction is null, and throws IllegalStateException if the result was consumed.

  • In a Row object, which represents a row returned from a database query, values from columns can be retrieved either by specifying a column name using the get(String name) method, or by specifying the column index using the get(int index) method. The sample application retrieves data by column index. Columns are numbered from 0.

  • A row is invalidated after consumption in the Result.map(BiFunction) mapping function.

  • The number, type, and characteristics of columns are described through RowMetadata.

  • Use the Flux.toIterable() method to transform the Flux object into a lazy Iterable blocking on Iterator.next() calls.

  • io.r2dbc.spi.Statement

    Creates a statement to execute on the server.

    io.r2dbc.spi.Result

    Contains the result-set from the server.

    io.r2dbc.spi.Row

    Contains a single row.

    io.r2dbc.spi.RowMetadata

    Contains metadata for a row.

    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import io.r2dbc.spi.Connection;
    import io.r2dbc.spi.Statement;
    import reactor.core.publisher.Mono;
    
    // Main Application Class
    public class App {
    
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static Connection conn;
    
       // Main Process
       public static void main(String[] args) {
          //Initialize Connection Factory
          initConnectionFactory();
    
          // Insert a contact
          insertContact("John", "Smith", "js@example.com");
       }
    
       public static void initConnectionFactory() {
    
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                .host("192.0.2.1").port(3306)
                .username("db_user").password("db_user_password")
                .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
          }
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Issue encountered while getting connection");
             e.printStackTrace();
          }
       }
    
       public static void insertContact(String first_name, String last_name, String email) {
    
          try {
             //Initialize a Connection
             conn = connFactory.create().block();
    
             // Initialize Statement
             Statement stmnt = conn.createStatement(
                "INSERT INTO test.contact (first_name, last_name, email) VALUES (?, ?, ?)");
    
             // Bind Values to Statement
             stmnt.bind(0, first_name);
             stmnt.bind(1, last_name);
             stmnt.bind(2, email);
    
             // Execute Statement
             Mono.from(stmnt.execute()).subscribe();
    
          }
          // Catch Exception
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Issue encountered while adding contact");
             e.printStackTrace();
          } finally {
             // Close Connection
             conn.close();
          }
       }
    }
    SELECT * FROM test.contact;
    +----+------------+-----------+----------------+
    | id | first_name | last_name | email          |
    +----+------------+-----------+----------------+
    |  1 | John       | Smith     | js@example.com |
    +----+------------+-----------+----------------+
    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import io.r2dbc.spi.Connection;
    import io.r2dbc.spi.Statement;
    import io.r2dbc.spi.Result;
    import io.r2dbc.spi.Row;
    import io.r2dbc.spi.RowMetadata;
    import reactor.core.publisher.Flux;
    
    public class App {
    
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
       private static Connection conn;
    
       public static void main(String[] argv) {
    
          //Initialize Connection Factory
          initConnectionFactory();
    
          // Print contacts
          printContactList();
       }
    
       public static void initConnectionFactory() {
    
          try {
             // Configure the Connection
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
          }
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Issue encountered while getting connection");
             e.printStackTrace();
          } finally {
          }
       }
    
       public static void printContactList() {
    
          try {
             //Initialize a Connection
             conn = connFactory.create().block();
    
             // Initialize Statement
             Statement stmnt = conn.createStatement(
                "SELECT first_name, last_name, email FROM test.contact");
    
             // Execute Statement and Iterate over the Result-set
             for (String contact_entry : Flux.from(stmnt.execute()).flatMap( res ->
                res.map( (row, metadata) -> {
    
                return String.format( "- %s %s <%s>",
                   // Get First Name
                   row.get(0, String.class),
    
                   //  Get Last Name
                   row.get(1, String.class),
    
                   //Get Email
                   row.get(2, String.class));
             })).toIterable()) {
    
                System.out.println(contact_entry);
             }
          }
          // Catch Exception
          catch (java.lang.IllegalArgumentException e) {
             System.err.println("Encountered issue querying contact list");
             e.printStackTrace();
          } finally {
             // Close Connection
             conn.close();
          }
       }
    }
    John Smith <js@example.com>

    Code Example: INSERT

    Code Example: SELECT

    Example output:

    Setup for Examples
    Setup for Examples
    spinner

    Allows you to execute several SQL statements in a single call. The statements should be separated by the ; delimiter. For example, the following string would execute two INSERT statements: INSERT INTO a VALUES('b'); INSERT INTO c VALUES('d'); Enabling multi-query functionality might be a security risk, because malicious users could use it for SQL injection attacks.

    boolean

    false

    allowPipelining

    Allows queries to be executed in a pipeline, so that the next query is sent to the server before the previous query has finished execution.

    boolean

    true

    allowPublicKeyRetrieval

    Allows the RSA public key to be retrieved from the server, rather than from the cachingRsaPublicKey or rsaPublicKey parameters. It is generally more secure to configure the RSA public key using the cachingRsaPublicKey or rsaPublicKey parameters. The RSA public key only applies when connecting to MySQL with the sha256_password or caching_sha2_password authentication plugins.

    boolean

    false

    autocommit

    Sets default value on connection initialization.

    boolean

    true

    cachingRsaPublicKey

    Configures the RSA public key. The RSA public key only applies when connecting to MySQL with the sha256_password or caching_sha2_password authentication plugins.

    String

    clientSslCert

    Configures the TLS client certificate. The TLS client certificate is only required when TLS client authentication is required. The parameter can be specified in 3 different formats: • Specify the absolute path to a PEM or DER certificate file: .clientSslCert("/path/to/cert.pem") • Specify the path to a PEM or DER certificate file relative to the Java CLASSPATH: .clientSslCert("classpath:relative/cert.pem") • Specify a PEM or DER certificate string: .clientSslCert("CERTIFICATE_STRING")

    String

    clientSslKey

    Configures the TLS client private key. The TLS client private key is only required when TLS client authentication is required.

    String

    clientSslPassword

    Configures the password for the TLS client private key. This is only required when the clientSslKey parameter refers to an encrypted private key file.

    charsequence

    connectionAttributes

    Sets client attributes that are sent to the server. When is enabled on the server, the client attributes can be queried from the performance_schema.session_connect_attrs and performance_schema.session_account_connect_attrs tables. Client attributes can be used to identify which client or application is using each connection.

    Map<String,String>

    connectTimeout

    Sets the connection timeout.

    duration

    10s

    database

    Default database to use when establishing the connection.

    string

    fallbackToSystemKeyStore

    Indicate if keystore default implementation can be used. Connector use keystore option if set or if not, use javax.net.ssl.keyStore* system properties to load keystore if this option is enable

    boolean

    false

    fallbackToSystemTrustStore

    Indicate if truststore default implementation can be used. Connector use serverSslCert option if set or if not, use java default truststore if this option is enable

    boolean

    false

    host

    IP address or DNS of the database server. Multiple hosts can be set by using comma separated list. If the first host is not reachable (timeout is connectTimeout), the driver uses the next host. Not used when using option socket.

    localhost

    isolationLevel

    Allows setting the default isolation level on connection creation. Possible values are: READ-COMMITTED, READ-UNCOMMITTED, REPEATABLE-READ, or SERIALIZABLE. For example: r2dbc:mariadb:USER@PASSWORD@HOST:PORT/DATABASE?isolationLevel=REPEATABLE-READ

    String

    null

    loopResources

    Permits sharing netty EventLoopGroup among multiple async libraries/framework.

    LoopResources

    pamOtherPwd

    Configures the secondary password. The secondary password is only required when the pam authentication plugin is used to implement multi-factor authentication (MFA). If multiple passwords are specified, the value must be URL encoded.

    string

    password

    User password.

    string

    permitRedirect

    Permit server redirection

    boolean

    true

    port

    Database server port number. Not used when using option socket.

    integer

    3306

    prepareCacheSize

    If useServerPrepStmts = true, caches the prepared information in a LRU cache to avoid re-preparation of command. On the next use of that command, only the prepared identifier and parameters (if any) will be sent to server. This enables the server to avoid reparsing query.

    int

    250

    restrictedAuth

    Can restrict authentication to the specified list of authentication plugins. The authentication plugins should be separated by commas. When set to an empty string, any authentication plugin can be used. By default, the following authentication plugins can be specified: mysql_native_password, mysql_clear_password, client_ed25519, dialog, sha256_password, or caching_sha2_password.

    string

    rsaPublicKey

    Configures the RSA public key. The RSA public key only applies when connecting to MySQL with the sha256_password or caching_sha2_password authentication plugins.

    string

    serverSslCert

    Configures the TLS server certificate or the server's TLS CA certificate. This parameter enables a self-signed certificate to be trusted. The parameter can be specified in 3 different formats: • Specify the absolute path to a PEM or DER certificate file: serverSslCert("/path/to/cert.pem") • Specify the path to a PEM or DER certificate file relative to the Java CLASSPATH: .serverSslCert("classpath:relative/cert.pem") • Specify a PEM or DER certificate string: .serverSslCert("CERTIFICATE_STRING")

    string

    sessionVariables

    Sets session values of system variables upon successful connection. The value should be set to a mapping of variables to values. For example, map.put("sql_mode", "ORACLE") or map.put("log_warnings", "5") The values of session variables can be retrieved using SHOW SESSION VARIABLES.

    Map<String,String>

    socket

    Configures the path to the Unix domain socket. Connecting to a Unix domain socket can be faster than connecting via TCP/IP. Connecting to a Unix domain socket also allows authentication to occur using the . Unix domain socket connections are only supported when the server is on the same system as the client.

    string

    sslContextBuilderCustomizer

    Used with sslMode=TUNNEL, enables use of a customized SSL Context Builder. By default, SSL tunnel mode does not validate tunnel certificates and hostnames. This option permits the use of certificates, and setting the required protocol and ciphers to create a tunnel socket.

    UnaryOperator

    sslMode

    Sets the TLS mode. Possible values are:DISABLE - TLS is disabled.TRUST - TLS is only used for data-in-transit encryption. The TLS server certificate is not verified, and the server's hostname is not validated against the certificate. MariaDB recommends only using this TLS mode for development.TUNNEL - Enables use of a use pre-existing SSL tunnel.VERIFY_CA - TLS is used for data-in-transit encryption, and the TLS server certificate is verified. The server's hostname is not validated against the certificate.VERIFY_FULL - TLS is used for data-in-transit encryption, and the TLS server certificate is verified, and the server's hostname is validated against the certificate.

    SslMode

    DISABLE

    sslTunnelDisableHostVerification

    When the sslMode connection parameter is set to SslMode.TUNNEL, host verification can be disabled by setting this connection parameter to true.

    boolean

    false

    tcpAbortiveClose

    This option can be used in environments where connections are created and closed in rapid succession. Often, it is not possible to create a socket in such an environment after a while, since all local "ephemeral" ports are used up by TCP connections in TCP_WAIT state. Using tcpAbortiveClose works around this problem by resetting TCP connections (abortive or hard close) rather than doing an orderly close.

    boolean

    false

    tcpKeepAlive

    Sets socket to keep alive.

    boolean

    false

    timezone

    This option permits forcing a session timezone in case of a client having a different timezone compared to the server. Possible values are:disable (default) : connector doesn't change time_zoneauto : client will use client default timezone: connector will set connection variable to the valueSince 1.2.0

    string

    disable

    tinyInt1isBit

    Configures how the connector handles BIT(1) and TINYINT(1) values in result sets. When set to true, the values are handled as boolean objects. When set to false, the values are handled as int objects.

    boolean

    true

    tlsProtocol

    Configures the supported set of TLS protocol versions. The value can be set to a comma-separated list of TLS protocol versions. For example: .tlsProtocol(("TLSv1.2",TLSv1.3"))

    List

    java default

    transactionReplay

    Saves commands in transactions. If a failover occurs during a transaction, the connector can automatically reconnect and replay transactions, making failover completely transparent. The driver will buffer up commands in a transaction until an inner limit is reached. A huge command may temporarily disable transaction buffering for current transactions. Commands must be idempotent only (queries can be "re-playable").

    boolean

    false

    username

    User of access database.

    string

    useServerPrepStmts

    Configures whether queries with parameters are evaluated using server-side prepared statements or client-side prepared statements. When server-side prepared statements are used, queries are transmitted using the binary protocol by default, but the text protocol can be used by prefixing the query string with /text/. When client-side prepared statements are used, queries are always transmitted using the text protocol.

    boolean

    false

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    Overview

    Connection Parameters

    allowMultiQueries

    spinner

    DatabaseClient.execute(String sql)

    Execute any DML statement.

    DatabaseClient.select()

    Execute a SELECT statement.

    DatabaseClient.insert()

    Execute a INSERT statement.

    DatabaseClient.update()

    Execute a UPDATE statement.

    DatabaseClient.delete()

    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import org.springframework.data.r2dbc.core.DatabaseClient;
    
    import reactor.test.StepVerifier;
    
    // Main Application Class
    public class App {
    
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
    
       private static DatabaseClient client;
    
       // Main Process
       public static void main(String[] args) {
    
          try {
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
             // Instantiate a Database Client
             client = DatabaseClient.create(connFactory);
    
             // Add First Contact
             client.insert()
                .into(Contact.class)
                .using(new Contact(1, "Kai", "Devi", "kai.devi@example.com"))
                .then()
                .as(StepVerifier::create)
                .verifyComplete();
    
             // Add Second Contact
             client.insert()
                .into(Contact.class)
                .using(new Contact(2, "Lee", "Wang", "kai.devi@example.com"))
                .then()
                .as(StepVerifier::create)
                .verifyComplete();
    
             // Add Third Contact
             client.insert()
                .into(Contact.class)
                .using(new Contact(3, "Dani", "Smith", "dani.smith@example.com"))
                .then()
                .as(StepVerifier::create)
                .verifyComplete();
    
          } catch (IllegalArgumentException e) {
             e.printStackTrace();
          } catch (io.r2dbc.spi.R2dbcNonTransientResourceException e) {
             e.printStackTrace();
          }
       }
    }
    SELECT * FROM test.contact;
    +----+------------+-----------+------------------------+
    | id | first_name | last_name | email                  |
    +----+------------+-----------+------------------------+
    |  1 | John       | Smith     | john.smith@example.com |
    +----+------------+-----------+------------------------+
    //Module Imports
    import org.mariadb.r2dbc.MariadbConnectionConfiguration;
    import org.mariadb.r2dbc.MariadbConnectionFactory;
    import org.springframework.data.r2dbc.core.DatabaseClient;
    import reactor.test.StepVerifier;
    
    // Main Application Class
    public class App {
       // Connection Configuration
       private static MariadbConnectionConfiguration conf;
       private static MariadbConnectionFactory connFactory;
    
       private static DatabaseClient client;
    
       // Main Process
       public static void main(String[] args) {
          try {
             conf = MariadbConnectionConfiguration.builder()
                  .host("192.0.2.1").port(3306)
                  .username("db_user").password("db_user_password")
                  .database("test").build();
    
             // Instantiate a Connection Factory
             connFactory = new MariadbConnectionFactory(conf);
    
             // Instantiate a Database Client
             client = DatabaseClient.create(connFactory);
    
             // Select all rows
             client.select()
                .from(Contact.class)
                .fetch().all()
                .doOnNext(it -> System.out.println(it))
                .as(StepVerifier::create)
                .expectNextCount(3)
                .verifyComplete();
    
             // Select the first row
             client.select()
                .from(Contact.class)
                .fetch().first()
                .doOnNext(it -> System.out.println(it))
                .as(StepVerifier::create)
                .expectNextCount(1)
                .verifyComplete();
    
             // Select all rows with explicit query
             client.execute("SELECT id, first_name,last_name,email FROM contact")
                .as(Contact.class)
                .filter(s -> s.fetchSize(25))
                .fetch().all()
                .doOnNext(it -> System.out.println(it))
                .as(StepVerifier::create)
                .expectNextCount(3)
                .verifyComplete();
    
             // Select single column
             client.select()
                .from(Contact.class)
                .map((row, rowMetadata) -> row.get("first_name", String.class))
                .all()
                .doOnNext(it -> System.out.println(it))
                .as(StepVerifier::create)
                .expectNextCount(3)
                .verifyComplete();
    
          } catch (IllegalArgumentException e) {
             e.printStackTrace();
          } catch (io.r2dbc.spi.R2dbcNonTransientResourceException e) {
             e.printStackTrace();
          }
       }
    }
    //Output from first query
    Contact [id=1, first_name=Kai, last_name=Devi, email=kai.devi@example.com]
    Contact [id=2, first_name=Lee, last_name=Wang, email=lee.wang@example.com]
    Contact [id=3, first_name=Dani, last_name=Smith, email=dani.smith@example.com]
    
    //Output from second query
    Contact [id=1, first_name=Kai, last_name=Devi, email=kai.devi@example.com]
    
    //Output from third query
    Contact [id=1, first_name=Kai, last_name=Devi, email=kai.devi@example.com]
    Contact [id=2, first_name=Lee, last_name=Wang, email=lee.wang@example.com]
    Contact [id=3, first_name=Dani, last_name=Smith, email=dani.smith@example.com]
    
    //Output from fourth query
    Kai
    Lee
    Dani

    Code Example: INSERT, UPDATE, DELETE

    Code Example: SELECT

    Setup for Examples
    Setup for Examples
    spinner

    Execute a DELETE statement.

    Repositories with MariaDB Connector/R2DBC (Spring Data)

    Spring Data repositories with MariaDB Connector/R2DBC use ReactiveCrudRepository and JavaConfig to implement reactive CRUD, with ApplicationConfig, Entity, Repository, and Service classes.

    Overview

    Java developers can use MariaDB Connector/R2DBC to connect to MariaDB database products using the Reactive Relational Database Connectivity (R2DBC) API. R2DBC operations are non-blocking, which makes R2DBC more scalable than Java's standard JDBC API. MariaDB Connector/R2DBC can be used with the very popular Spring Data framework, which can provide support for repositories, object mapping, and transaction management.

    Spring Data Repositories technology is an abstraction that implements a data access layer over the underlying datastore. Spring Data Repositories reduce the boilerplate code required to access a datastore. Spring Data repositories can be used with the MariaDB/R2DBC connector.

    Code Example: Example Application

    The following example depends on the environment created in Setup for Examples.

    Repository Classes Used

    In the sections below, we will build an example application that uses a Spring Data Repository. Some annotations that scan packages for repository classes require that the classes be in a named package rather than the default package. The classes in this example application will be in the springdata package.

    The example application contains the following classes:

    Class
    Description

    We will need to adapt the entity class for Spring Data Repositories:

    • The entity class is in the springdata package instead of the default package. Spring Data Repositories require repository related classes and interfaces to be in a named package instead of the default package to be able to scan for them.

    • The entity class includes a constructor that defines parameters for all the fields except the identifier id field. * * * This constructor will be used to add new contacts in .

    • The entity class also includes a no-args default constructor.

    The org.springframework.data.repository.reactive.ReactiveCrudRepository interface is the entrypoint for Spring Data R2DBC repositories. The ReactiveCrudRepository interface is used for generic CRUD operations on a repository for a specific type. This repository follows reactive paradigms and uses Project Reactor types which are built on top of Reactive Streams.

    The ReactiveCrudRepository interface provides methods listed in following table:

    Method
    Description

    The sample repository class is listed:

    • The findByFirstname(String firstname) method finds entities matching a given first name.

    • The findById(int id) method finds entities matching a given id.

    • An implementation class for the ContactRepository interface is not provided as the Spring Data Repositories framework generates the implementation class as needed.

    A JavaConfig configuration class is used to enable Spring Data Repositories. A JavaConfig configuration class is a plain old Java object (POJO). A POJO is an ordinary Java object without any special constraints of Java object models or conventions. The sample configuration file used is listed:

    • The configuration class ApplicationConfig extends the AbstractR2dbcConfiguration class and provides only one method connectionFactory(), which is used by the Spring Data Repositories framework to obtain a ConnectionFactory instance to the MariaDB database using a R2DBC driver

    • The ApplicationConfig extends the AbstractR2dbcConfiguration class, which is the base class for Spring Data R2DBC configuration containing bean declarations that must be registered for Spring Data R2DBC.

    • The ApplicationConfig class is annotated with @Configuration, which indicates that a class declares @Bean annotated methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.

    The R2DBC Connection URL format is r2dbc:driver[:protocol]://[user:password@]host[:port][/path][?option=value]

    A service class is used to perform CRUD operations with the Spring Data R2DBC repository. The following develops a service application to test the Spring Data R2DBC repository:

    • To update an existing contact, create a Contact entity instance with the all-args constructor, which is the constructor that defines all fields including the identifier field id as parameters. Subsequently, call method ReactiveCrudRepository.save(S entity) to save the entity. To verify that the contact has been updated call the ReactiveCrudRepository.findByFirstname method.

    Run the service class springdata.RepositoryService and for the sample table data and the sample application the following output is made:

    Run a SQL query to verify the test.contact table data we started with got deleted and three new contacts are added:

    This page is: Copyright © 2026 MariaDB. All rights reserved.

    The Service class that performs CRUD (Create, Read, Update Delete) operations.

    findById(ID id)

    Retrieves an entity by its id. It returns a Mono emitting the entity with the given id or Mono.empty() if none found.

    findById(Publisher id)

    Retrieves an entity by its id supplied by a Publisher. It returns a Mono emitting the entity with the given id or Mono.empty() if none found.

    findAll()

    Returns all instances of the type. It returns a Flux emitting all entities.

    findAllById(Iterable ids)

    Returns all instances of the type T with the given ids. If some or all ids are not found, no entities are returned for these ids. Note that the order of elements in the result is not guaranteed. It returns a Flux emitting the found entities. The size can be equal or less than the number of given ids.

    findAllById(Publisher idStream)

    Returns all instances of the type T with the given ids supplied by a Publisher. If some or all ids are not found, no entities are returned for these ids. Note that the order of elements in the result is not guaranteed. It returns a Flux emitting the found entities.

    count()

    Returns the number of entities available. It returns a Mono emitting the number of entities.

    deleteById(ID id)

    Deletes the entity with the given id. It returns a Mono signaling when operation has completed.

    deleteById(Publisher id)

    Deletes the entity with the given id supplied by a Publisher. It returns a Mono signaling when operation has completed.

    delete(T entity)

    Deletes a given entity. It returns a Mono signaling when operation has completed.

    deleteAll(Iterable<? extends T> entities)

    Deletes the given entities. It returns a Mono signaling when operation has completed.

    deleteAll(Publisher<? extends T> entityStream)

    Deletes the given entities supplied by a Publisher. It returns a Mono signaling when operation has completed.

    deleteAll()

    Deletes all entities managed by the repository. It returns a Mono signaling when operation has completed.

    The ApplicationConfig class is annotated with @EnableR2dbcRepositories, which indicates the reactive relational repositories should be activated using R2DBC. A base package class is specified as ContactRepository.class using the basePackageClasses annotation attribute. If no base package is configured through either value(), basePackages(), or basePackageClasses() it will scan the package of the annotated class.

  • The ApplicationConfig class is annotated with @ComponentScan, which configures component scanning directives for use with @Configuration classes. A base package class is specified as RepositoryService.class using the basePackageClasses annotation attribute. With the @ComponentScan set, the RepositoryService.class is used within the Spring Data Repositories framework. If no base package is configured through either value(), basePackages(), or basePackageClasses() it will scan the package of the annotated class, which must be a named package and not the default package.

  • The connectionFactory() method returns a ConnectionFactory instance and is annotated with @Bean to indicate that the method produces a bean to be managed by the Spring container. A new ConnectionFactory is created using the static method ConnectionFactories.get(String url).

  • springdata.ApplicationConfig

    The JavaConfig configuration class that enables Spring Data repositories.

    springdata.Contact

    The Entity class that models the table.

    springdata.ContactRepository

    The Repository interface.

    package springdata;
    
    // Imports the @Id annotation type, which demarcates an identifier.
    //Module Imports
    import org.springframework.data.annotation.Id;
    
    // This is an Entity class
    // It has the same name as the text.contact table
    public class Contact {
    
       // The class members correspond to columns
       // in the test.contact table
       private int id;
       private String first_name;
       private String last_name;
       private String email;
    
       // Constructor
       public Contact() {
       }
    
       // Constructor
       public Contact(String first_name, String last_name, String email) {
    
          this.first_name = first_name;
          this.last_name = last_name;
          this.email = email;
       }
    
       // Constructor
       public Contact(int id, String first_name, String last_name, String email) {
          this.id = id;
          this.first_name = first_name;
          this.last_name = last_name;
          this.email = email;
       }
    
       // The @Id annotation indicates that this field
       // is the primary key column
       @Id
       public int getId() {
          return id;
       }
    
       public String getFirst_name() {
          return first_name;
       }
    
       public String getLast_name() {
          return last_name;
       }
    
       public String getEmail() {
          return email;
       }
    
       @Override
       public String toString() {
          return "Contact [id=" + id + ", first_name=" + first_name + ", last_name=" + last_name + ", email=" + email
                + "]";
       }
    }

    save(S entity)

    Saves a given entity. Returns a Mono for the saved entity. Use the returned instance for further operations as the save operation might have changed the entity instance completely. The save(S entity) method updates an existing entity if the Entity object arguments include the identifier field. The save(S entity) method adds a new entity if the Entity object arguments do not include the identifier field.

    saveAll(Iterable entities)

    Saves all given entities. It returns a Flux emitting the saved entities.

    saveAll(Publisher entityStream)

    Saves all given entities. It returns a Flux emitting the saved entities..

    package springdata;
    
    //Module Imports
    import reactor.core.publisher.Flux;
    import org.springframework.data.r2dbc.repository.Query;
    import org.springframework.data.repository.reactive.ReactiveCrudRepository;
    
    // ReactiveCrudRepository<Contact, Integer>:
    //   Entity Class: Contact
    //   Data type of identifier: Integer
    interface ContactRepository extends ReactiveCrudRepository<Contact, Integer> {
    
       // The Query annotation provides an SQL statement corresponding to the method
       @Query("select id, first_name, last_name, email from contact c where c.first_name = :first_name")
       Flux<Contact> findByFirstname(String firstname);
    
       @Query("select id, first_name, last_name, email from contact c where c.id = :id")
       Flux<Contact> findById(int id);
    }
    package springdata;
    
    //Module Imports
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
    import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
    
    import io.r2dbc.spi.ConnectionFactories;
    import io.r2dbc.spi.ConnectionFactory;
    
    @Configuration
    @EnableR2dbcRepositories(basePackageClasses = ContactRepository.class)
    @ComponentScan(basePackageClasses = RepositoryService.class)
    class ApplicationConfig extends AbstractR2dbcConfiguration {
       @Bean
       public ConnectionFactory connectionFactory() {
          return ConnectionFactories.get("r2dbc:mariadb://connr2dbc_test:db_user_password@192.0.2.50:3306/test");
       }
    }
    package springdata;
    
    //Module Imports
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.stereotype.Service;
    
    import reactor.test.StepVerifier;
    
    // The @Service annotation indicates that the class is a "Service".
    // Spring Data Repositories framework auto-discovers the service class
    // through classpath scanning because we have set the @ComponentScan
    // annotation in ApplicationConfig to scan for RepositoryService.class.
    @Service
    public class RepositoryService {
    
       // The @Autowired annotation indicates that the field is to be autowired
       // by Spring's dependency injection facilities.
       @Autowired
       private static ContactRepository repository;
    
       // The ApplicationContext provides Bean factory methods for
       // accessing application components.
       private static ApplicationContext ctx;
    
       public static void main(String[] args) {
    
          try {
             // The AnnotationConfigApplicationContext class is a standalone application context,
             // accepting component classes as input, in particular @Configuration-annotated
             // classes such as the ApplicationConfig class we developed.
             ctx = new AnnotationConfigApplicationContext(ApplicationConfig.class);
    
             // Returns the bean instance that uniquely matches the ContactRepository.class
             repository = ctx.getBean(ContactRepository.class);
             RepositoryService repoService = new RepositoryService();
             repoService.crud();
          } catch (Exception e) {
             System.out.println();
          } finally {
             // ...
          }
       }
    
       public void crud() {
    
          // Print number of rows
          System.out.println("Number of contacts in database is " + repository.count().block());
    
          // Delete all data
          repository.deleteAll().block();
    
          // Print number of rows again
          System.out.println("Number of contacts in database is " + repository.count().block());
    
          // Insert one row
          // ID is auto-generated
          Contact contact = new Contact("John", "Smith", "john.smith@gmail.com");
          repository.save(contact)
             .as(StepVerifier::create)
             .expectNextCount(1)
             .verifyComplete();
    
          // Insert another row
          // ID is auto-generated
          contact = new Contact("Johnny", "Smith", "johnny.smith@gmail.com");
          repository.save(contact)
             .as(StepVerifier::create)
             .expectNextCount(1)
             .verifyComplete();
    
          // Insert another row
          // ID is auto-generated
          contact = new Contact("Joe", "Smith", "joe.smith@gmail.com");
          repository.save(contact)
             .as(StepVerifier::create)
             .expectNextCount(1)
             .verifyComplete();
    
          // Print all rows
          repository.findAll()
             .doOnNext(it -> System.out.println(it)).as(StepVerifier::create)
             .expectNextCount(3)
             .verifyComplete();
    
          // Print rows with first name "John"
          repository.findByFirstname("John")
             .doOnNext(it -> System.out.println(it))
             .as(StepVerifier::create)
             .expectNextCount(1)
             .verifyComplete();
    
          // Print row with ID 1
          repository.findById(1)
             .doOnNext(it -> System.out.println(it))
             .as(StepVerifier::create)
             .expectNextCount(1)
             .verifyComplete();
    
           // Update email for contact with id 1
          // ID is explicitly provided
          contact = new Contact(1, "John", "Smith", "johnsmith@gmail.com");
          repository.save(contact)
             .as(StepVerifier::create)
             .expectNextCount(1)
             .verifyComplete();
    
          // Print rows with first name "John"
          repository.findByFirstname("John")
             .doOnNext(it -> System.out.println(it))
             .as(StepVerifier::create)
             .expectNextCount(1)
             .verifyComplete();
       }
    }
    Number of contacts in database is 0
    Number of contacts in database is 0
    Contact [id=1, first_name=John, last_name=Smith, email=john.smith@example.com]
    Contact [id=2, first_name=Johnny, last_name=Smith, email=johnny.smith@example.com]
    Contact [id=3, first_name=Joe, last_name=Smith, email=joe.smith@example.com]
    Contact [id=1, first_name=John, last_name=Smith, email=john.smith@example.com]
    Contact [id=1, first_name=John, last_name=Smith, email=john.smith@example.com]
    Contact [id=1, first_name=John, last_name=Smith, email=johnsmith@example.com]
    SELECT * FROM test.contact;
    +----+------------+-----------+---------------------------+
    | id | first_name | last_name | email                     |
    +----+------------+-----------+---------------------------+
    |  1 | John       | Smith     | johnsmith@example.com     |
    +----+------------+-----------+---------------------------+
    |  2 | Johnny     | Smith     | johnny.smith@example.com  |
    +----+------------+-----------+---------------------------+
    |  3 | Joe        | Smith     | joe.smith@example.com     |
    +----+------------+-----------+---------------------------+

    Adapting the Entity

    The changes are:

    Create a Repository

    Create a JavaConfig Configuration

    Create a Service

    Test the Service

    previously created
    Creating a Service Class
    spinner
    springdata.RepositoryService
    See all MariaDB Connector/R2DBC releases
    1.4.1
    DELETE
    INSERT
    REPLACE
    SELECT
    UPDATE
    ALTER TABLE
    CREATE TABLE
    DROP TABLE
    CREATE DATABASE
    TRUNCATE TABLE
    MariaDB Client
    SELECT
    information_schema.TABLES
    ALTER TABLE
    CREATE TABLE
    DROP TABLE
    CREATE DATABASE
    TRUNCATE
    ALTER TABLE
    CREATE TABLE
    DROP TABLE
    CREATE DATABASE
    TRUNCATE TABLE
    DELETE
    INSERT
    REPLACE
    SELECT
    UPDATE
    DELETE
    INSERT
    REPLACE
    SELECT
    UPDATE
    INSERT
    UPDATE
    DELETE
    autocommit
    performance_schema
    unix_socket authentication plugin