Spring boot3 is already M1, and recently the group of people are also starting to start working on Reactive+Spring Boot3. Following everyone's pace, I will also get a starter of the project. We will use java17+Spring Boot3+r2dbc+Reactive stack to tell you. Everyone is welcome to discuss it. (For responsiveness, please asynchronously into the previous article for a detailed introduction.)
r2dbc
Reactor also has a Spring WebFlux framework based on it. Including reactive technologies such as rxjava. We actually already have many excellent responsive processing frameworks at the application layer.
But there is a problem that all frameworks need to obtain the underlying data, and basically the underlying reading and writing of relational databases are still synchronized.
To solve this problem, two standards emerged, one is ADBC (Asynchronous Database Access API) proposed by oracle, and the other is R2DBC (Reactive Relational Database Connectivity) proposed by Pivotal.
R2DBC is designed based on the Reactive Streams standard. By using R2DBC, you can use the reactive API to manipulate data.
At the same time, R2DBC is just an open standard, and each specific database connection implementation needs to implement this standard.
Today, we will use r2dbc-h2 as an example to explain the use of r2dbc in Spring webFlux.
Engineering dependency
Here is a list
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="/POM/4.0.0" xmlns:xsi="http:///2001/XMLSchema-instance" xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0."> <modelVersion>4.0.0</modelVersion> <parent> <groupId></groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.0-M1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId></groupId> <artifactId>springboot3demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot3demo</name> <description>Demo project for Spring Boot</description> <properties> <>17</> </properties> <dependencies> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-data-r2dbc</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-groovy-templates</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-hateoas</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId></groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-h2</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId></groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId></groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId></groupId> <artifactId>reactor-test</artifactId> <!-- <version>3.4.14</version>--> <!-- <scope>compile</scope>--> </dependency> </dependencies> <build> <plugins> <plugin> <groupId></groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>/snapshot</url> <releases> <enabled>false</enabled> </releases> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>/snapshot</url> <releases> <enabled>false</enabled> </releases> </pluginRepository> </pluginRepositories> </project>
Configuration File
Here we only configure r2dbc link information
Configuration class
Used to configure default links and create initialized data
package .; import ; import io.; import io.; import io.; import ; import ; import ; import ; import ; import ; import static io..*; @Configuration @ConfigurationProperties(prefix = "r2dbc") public class DBConfig { private String url; private String user; private String password; public String getUrl() { return url; } public void setUrl(String url) { = url; } public String getUser() { return user; } public void setUser(String user) { = user; } public String getPassword() { return password; } public void setPassword(String password) { = password; } @Bean public ConnectionFactory connectionFactory() { ("url ==> "+url); ConnectionFactoryOptions baseOptions = (url); ob = ().from(baseOptions); if (!(user)) { ob = (USER, user); } if (!(password)) { ob = (PASSWORD, password); } return (()); } @Bean public CommandLineRunner initDatabase(ConnectionFactory cf) { return (args) -> (()) .flatMap(c -> (() .add("drop table if exists Users") .add("create table Users(" + "id IDENTITY(1,1)," + "firstname varchar(80) not null," + "lastname varchar(80) not null)") .add("insert into Users(firstname,lastname)" + "values('Jacky','Li')") .add("insert into Users(firstname,lastname)" + "values('Doudou','Li')") .add("insert into Users(firstname,lastname)" + "values('Maimai','Li')") .execute()) .doFinally((st) -> ()) ) .log() .blockLast(); } }
bean
Create user bean
package .; import ; public class Users { @Id private Long id; private String firstname; private String lastname; public Users(){ } public Users(Long id, String firstname, String lastname) { = id; = firstname; = lastname; } public Long getId() { return id; } public void setId(Long id) { = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { = lastname; } @Override public String toString() { return "User{" + ", firstname='" + firstname + '\'' + ", lastname='" + lastname + '\'' + '}'; } }
DAO
The dao code list is as follows, including query list, query by id, and creating user
package .; import io.; import io.; import ..R2dbcEntityTemplate; import ; import ; import ; import ; import .; import static .; import static ; @Component public class UsersDao { private ConnectionFactory connectionFactory; private R2dbcEntityTemplate template; public UsersDao(ConnectionFactory connectionFactory) { = connectionFactory; = new R2dbcEntityTemplate(connectionFactory); } public Mono<Users> findById(long id) { return (query(where("id").is(id)),); // return (()) // .flatMap(c -> (("select id,firstname,lastname from Users where id = $1") // .bind("$1", id) // .execute()) // .doFinally((st) -> close(c))) // .map(result -> ((row, meta) -> // new Users(("id", ), // ("firstname", ), // ("lastname", )))) // .flatMap( p -> (p)); } public Flux<Users> findAll() { return ().all(); // return (()) // .flatMap((c) -> (("select id,firstname,lastname from users") // .execute()) // .doFinally((st) -> close(c))) // .flatMapMany(result -> (((row, meta) -> { // Users acc = new Users(); // (("id", )); // (("firstname", )); // (("lastname", )); // return acc; // }))); } public Mono<Users> createAccount(Users account) { return (()) .flatMap(c -> (()) .then((("insert into Users(firstname,lastname) values($1,$2)") .bind("$1", ()) .bind("$2", ()) .returnGeneratedValues("id") .execute())) .map(result -> ((row, meta) -> new Users(("id", ), (), ()))) .flatMap(pub -> (pub)) .delayUntil(r -> ()) .doFinally((st) -> ())); } private <T> Mono<T> close(Connection connection) { return (()) .then(()); } }
controller
Controller code list is as follows, including query list, query by id, and creating user, etc.
package .; import ; import ; import ; import ; import .*; import ; import ; import .; import .; @RestController public class UsersController { @Autowired private final UsersDao usersDao; public UsersController(UsersDao usersDao) { = usersDao; } @GetMapping("/users/{id}") public Mono<ResponseEntity<Users>> getUsers(@PathVariable("id") Long id) { return (id) .map(acc -> new ResponseEntity<>(acc, )) .switchIfEmpty((new ResponseEntity<>(null, HttpStatus.NOT_FOUND))); } @GetMapping("/users") public Flux<Users> getAllAccounts() { return (); } @PostMapping("/createUser") public Mono<ResponseEntity<Users>> createUser(@RequestBody Users user) { return (user) .map(acc -> new ResponseEntity<>(acc, )) .log(); } }
Startup class manifest:
package .springboot3demo; import ; import ; import ; import .; @SpringBootApplication @EnableConfigurationProperties() public class WebFluxR2dbcApp { public static void main(String[] args) { (, args); } }
OK, so we have completed the entire demo
Reference link:
/p/299069835
This is the article about springboot3+r2dbc responsive programming practice. For more related springboot3 r2dbc responsive programming content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!