IntroductionMySQL should be a very common database we use in our daily work. Although MySQL is now owned by Oracle, it is open source and its market share is still very high. Today we will introduce the use of r2dbc in mysql. Maven dependency of r2dbc-mysqlTo use r2dbc-mysql, we need to add the following Maven dependencies: <dependency> <groupId>dev.miku</groupId> <artifactId>r2dbc-mysql</artifactId> <version>0.8.2.RELEASE</version> </dependency> Of course, if you want to use the snapshot version, you can do this: <dependency> <groupId>dev.miku</groupId> <artifactId>r2dbc-mysql</artifactId> <version>${r2dbc-mysql.version}.BUILD-SNAPSHOT</version> </dependency> <repository> <id>sonatype-snapshots</id> <name>SonaType Snapshots</name> <url>https://oss.sonatype.org/content/repositories/snapshots</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> Creating a connectionFactoryThe code for creating the connectionFactory actually uses the standard interface of r2dbc, so it is basically the same as the creation code of h2 mentioned earlier: // Notice: the query string must be URL encoded ConnectionFactory connectionFactory = ConnectionFactories.get( "r2dbcs:mysql://root:[email protected]:3306/r2dbc?" + "zeroDate=use_round&" + "sslMode=verify_identity&" + "useServerPrepareStatement=true&" + "tlsVersion=TLSv1.3%2CTLSv1.2%2CTLSv1.1&" + "sslCa=%2Fpath%2Fto%2Fmysql%2Fca.pem&" + "sslKey=%2Fpath%2Fto%2Fmysql%2Fclient-key.pem&" + "sslCert=%2Fpath%2Fto%2Fmysql%2Fclient-cert.pem&" + "sslKeyPassword=key-pem-password-in-here" ) // Creating a Mono using Project Reactor Mono<Connection> connectionMono = Mono.from(connectionFactory.create()); The difference is that the parameters passed in by ConnectionFactories are different. We also support the Unix domain socket format: // Minimum configuration for unix domain socket ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc:mysql://root@unix?unixSocket=%2Fpath%2Fto%2Fmysql.sock") Mono<Connection> connectionMono = Mono.from(connectionFactory.create()); Similarly, we also support creating ConnectionFactory from ConnectionFactoryOptions: ConnectionFactoryOptions options = ConnectionFactoryOptions.builder() .option(DRIVER, "mysql") .option(HOST, "127.0.0.1") .option(USER, "root") .option(PORT, 3306) // optional, default 3306 .option(PASSWORD, "database-password-in-here") // optional, default null, null means has no password .option(DATABASE, "r2dbc") // optional, default null, null means not specifying the database .option(CONNECT_TIMEOUT, Duration.ofSeconds(3)) // optional, default null, null means no timeout .option(SSL, true) // optional, default sslMode is "preferred", it will be ignored if sslMode is set .option(Option.valueOf("sslMode"), "verify_identity") // optional, default "preferred" .option(Option.valueOf("sslCa"), "/path/to/mysql/ca.pem") // required when sslMode is verify_ca or verify_identity, default null, null means has no server CA cert .option(Option.valueOf("sslCert"), "/path/to/mysql/client-cert.pem") // optional, default null, null means has no client cert .option(Option.valueOf("sslKey"), "/path/to/mysql/client-key.pem") // optional, default null, null means has no client key .option(Option.valueOf("sslKeyPassword"), "key-pem-password-in-here") // optional, default null, null means there is no password for client key (ie "sslKey") .option(Option.valueOf("tlsVersion"), "TLSv1.3,TLSv1.2,TLSv1.1") // optional, default is auto-selected by the server .option(Option.valueOf("sslHostnameVerifier"), "com.example.demo.MyVerifier") // optional, default is null, null means use standard verifier .option(Option.valueOf("sslContextBuilderCustomizer"), "com.example.demo.MyCustomizer") // optional, default is no-op customizer .option(Option.valueOf("zeroDate"), "use_null") // optional, default "use_null" .option(Option.valueOf("useServerPrepareStatement"), true) // optional, default false .option(Option.valueOf("tcpKeepAlive"), true) // optional, default false .option(Option.valueOf("tcpNoDelay"), true) // optional, default false .option(Option.valueOf("autodetectExtensions"), false) // optional, default false .build(); ConnectionFactory connectionFactory = ConnectionFactories.get(options); // Creating a Mono using Project Reactor Mono<Connection> connectionMono = Mono.from(connectionFactory.create()); Or the following unix domain socket format: // Minimum configuration for unix domain socket ConnectionFactoryOptions options = ConnectionFactoryOptions.builder() .option(DRIVER, "mysql") .option(Option.valueOf("unixSocket"), "/path/to/mysql.sock") .option(USER, "root") .build(); ConnectionFactory connectionFactory = ConnectionFactories.get(options); Mono<Connection> connectionMono = Mono.from(connectionFactory.create()); Create a connection using MySqlConnectionFactoryIn the above example, we use the general r2dbc api to create a connection. Similarly, we can also use the unique MySqlConnectionFactory to create a connection: MySqlConnectionConfiguration configuration = MySqlConnectionConfiguration.builder() .host("127.0.0.1") .user("root") .port(3306) // optional, default 3306 .password("database-password-in-here") // optional, default null, null means has no password .database("r2dbc") // optional, default null, null means not specifying the database .serverZoneId(ZoneId.of("Continent/City")) // optional, default null, null means query server time zone when connection init .connectTimeout(Duration.ofSeconds(3)) // optional, default null, null means no timeout .sslMode(SslMode.VERIFY_IDENTITY) // optional, default SslMode.PREFERRED .sslCa("/path/to/mysql/ca.pem") // required when sslMode is VERIFY_CA or VERIFY_IDENTITY, default null, null means there is no server CA cert .sslCert("/path/to/mysql/client-cert.pem") // optional, default has no client SSL certificate .sslKey("/path/to/mysql/client-key.pem") // optional, default has no client SSL key .sslKeyPassword("key-pem-password-in-here") // optional, default has no client SSL key password .tlsVersion(TlsVersions.TLS1_3, TlsVersions.TLS1_2, TlsVersions.TLS1_1) // optional, default is auto-selected by the server .sslHostnameVerifier(MyVerifier.INSTANCE) // optional, default is null, null means use standard verifier .sslContextBuilderCustomizer(MyCustomizer.INSTANCE) // optional, default is no-op customizer .zeroDateOption(ZeroDateOption.USE_NULL) // optional, default ZeroDateOption.USE_NULL .useServerPrepareStatement() // Use server-preparing statements, default uses client-preparing statements .tcpKeepAlive(true) // optional, controls TCP Keep Alive, default is false .tcpNoDelay(true) // optional, controls TCP No Delay, default is false .autodetectExtensions(false) // optional, controls extension auto-detect, default is true .extendWith(MyExtension.INSTANCE) // optional, manually extend an extension into extensions, default using auto-detect .build(); ConnectionFactory connectionFactory = MySqlConnectionFactory.from(configuration); // Creating a Mono using Project Reactor Mono<Connection> connectionMono = Mono.from(connectionFactory.create()); Or the following unix domain socket method: // Minimum configuration for unix domain socket MySqlConnectionConfiguration configuration = MySqlConnectionConfiguration.builder() .unixSocket("/path/to/mysql.sock") .user("root") .build(); ConnectionFactory connectionFactory = MySqlConnectionFactory.from(configuration); Mono<Connection> connectionMono = Mono.from(connectionFactory.create()); Execute statementFirst, let's look at a simple statement without parameters: connection.createStatement("INSERT INTO `person` (`first_name`, `last_name`) VALUES ('who', 'how')") .execute(); // return a Publisher including one Result Then look at a statement with parameters: connection.createStatement("INSERT INTO `person` (`birth`, `nickname`, `show_name`) VALUES (?, ?name, ?name)") .bind(0, LocalDateTime.of(2019, 6, 25, 12, 12, 12)) .bind("name", "Some one") // Not one-to-one binding, call twice of native index-bindings, or call once of name-bindings. .add() .bind(0, LocalDateTime.of(2009, 6, 25, 12, 12, 12)) .bind(1, "My Nickname") .bind(2, "Naming show") .returnGeneratedValues("generated_id") .execute(); // return a Publisher including two Results. Note that if the parameter is null, you can use bindNull to bind the null value. Next, let's look at a batch execution operation: connection.createBatch() .add("INSERT INTO `person` (`first_name`, `last_name`) VALUES ('who', 'how')") .add("UPDATE `earth` SET `count` = `count` + 1 WHERE `id` = 'human'") .execute(); // return a Publisher including two Results. Execution of transactionsLet's look at an example of executing a transaction: connection.beginTransaction() .then(Mono.from(connection.createStatement("INSERT INTO `person` (`first_name`, `last_name`) VALUES ('who', 'how')").execute())) .flatMap(Result::getRowsUpdated) .thenMany(connection.createStatement("INSERT INTO `person` (`birth`, `nickname`, `show_name`) VALUES (?, ?name, ?name)") .bind(0, LocalDateTime.of(2019, 6, 25, 12, 12, 12)) .bind("name", "Some one") .add() .bind(0, LocalDateTime.of(2009, 6, 25, 12, 12, 12)) .bind(1, "My Nickname") .bind(2, "Naming show") .returnGeneratedValues("generated_id") .execute()) .flatMap(Result::getRowsUpdated) .then(connection.commitTransaction()); Using thread poolIn order to improve the execution efficiency of the database and reduce the overhead of establishing connections, general database connections will have the concept of connection pools. Similarly, r2dbc also has a connection pool called r2dbc-pool. r2dbc-pool dependencies: <dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-pool</artifactId> <version>${version}</version> </dependency> If you want to use a snapshot version, you can also specify it like this: <dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-pool</artifactId> <version>${version}.BUILD-SNAPSHOT</version> </dependency> <repository> <id>spring-libs-snapshot</id> <name>Spring Snapshot Repository</name> <url>https://repo.spring.io/libs-snapshot</url> </repository> Let's take a look at how to specify the database connection pool: ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc:pool:<my-driver>://<host>:<port>/<database>[?maxIdleTime=PT60S[&…]"); Publisher<? extends Connection> connectionPublisher = connectionFactory.create(); As you can see, we only need to add the pool driver to the connection URL. Similarly, we can also create it through ConnectionFactoryOptions: ConnectionFactory connectionFactory = ConnectionFactories.get(ConnectionFactoryOptions.builder() .option(DRIVER, "pool") .option(PROTOCOL, "postgresql") // driver identifier, PROTOCOL is delegated as DRIVER by the pool. .option(HOST, "…") .option(PORT, "…") .option(USER, "...") .option(PASSWORD, "…") .option(DATABASE, "…") .build()); Publisher<? extends Connection> connectionPublisher = connectionFactory.create(); // Alternative: Creating a Mono using Project Reactor Mono<Connection> connectionMono = Mono.from(connectionFactory.create()); Finally, you can also use the thread pool directly by creating a ConnectionPoolConfiguration: ConnectionFactory connectionFactory = ...; ConnectionPoolConfiguration configuration = ConnectionPoolConfiguration.builder(connectionFactory) .maxIdleTime(Duration.ofMillis(1000)) .maxSize(20) .build(); ConnectionPool pool = new ConnectionPool(configuration); Mono<Connection> connectionMono = pool.create(); // later Connection connection = …; Mono<Void> release = connection.close(); // released the connection back to the pool // application shutdown pool.dispose(); This is the end of this article about in-depth understanding of the use of r2dbc in mysql. For more relevant mysql r2dbc content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: How to implement Nginx reverse proxy for multiple servers
>>: JavaScript to implement retractable secondary menu
Preface When sharing a page, you hope to click th...
The specific steps of installing mysql5.7.18 unde...
Table of contents Using conditional types in gene...
Docker tag detailed explanation The use of the do...
1. The role of index Generally speaking, an index...
Using Navicat directly to connect via IP will rep...
When writing animations with JS, layout conversio...
This article mainly introduces common strategies ...
The following attributes are not very compatible w...
The connection method in MySQL table is actually ...
HTML meta tag HTML meta tags can be used to provi...
The command to delete images in docker is docker ...
In this article, I will explain in detail how to ...
1. Hot deployment: It means redeploying the entir...