如何使用R2DBC连接数据库?

本文介绍了R2DBC(反应式数据库连接)的概念,它是为了解决传统数据库不支持反应式编程的问题。通过引入R2DBC和相关依赖,可以在Spring Boot应用中使用H2数据库进行反应式数据操作。文章详细展示了如何配置pom.xml、application.yml,以及创建Usr实体、UsrRepository和UsrController,最后通过测试代码展示如何获取和保存数据。
摘要由CSDN通过智能技术生成

一、R2DBC是什么?

反应式编程能大大降低服务器的内存和线程需要量。但是并非所有数据库都能原生支持反应式编程。通常只有非关系型数据库支持反应式编程。为了使关系型数据库支持反应式编程,发明了R2DBC。

二、如何使用R2DBC

1. 使用Maven引入的依赖项

部分pom.xml

...
  <dependencies>
    <!-- Spring WebFlux依赖项 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <!-- Spring Data JPA依赖项 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- H2嵌入式数据库依赖项 -->
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <scope>runtime</scope>
    </dependency>
    <!-- R2DBC依赖项,用于使不支持反应式的数据库支持反应式 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-r2dbc</artifactId>
    </dependency>
    <!-- R2DBC-h2依赖项,为了使R2DBC能使用H2数据库 -->
    <dependency>
      <groupId>io.r2dbc</groupId>
      <artifactId>r2dbc-h2</artifactId>
      <scope>runtime</scope>
    </dependency>
    <!-- lombok依赖项,用于自动生成代码 -->
	<dependency>
	  <groupId>org.projectlombok</groupId>
	  <artifactId>lombok</artifactId>
	  <optional>true</optional>
	</dependency>
  </dependencies>
...

2. 配置文件

application.yml

spring: 
  r2dbc: 
    # 设置R2DBC的url。这里使用的h2数据库。基于内存。创建的数据库名是testdb
    url: r2dbc:h2:mem://./testdb
    username: sa
    password: 123456

3. Java文件

Usr.java

package model;

import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import lombok.AllArgsConstructor;
import lombok.Data;

@Table
@Data
@AllArgsConstructor
public class Usr {
	@Id
	private Integer id;
	private String firstname;
	private String lastname;
	
	boolean hasId() {
		return id != null;
	}
}

UsrRepository.java

package repository;

import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
import model.Usr;

public interface UsrRepository extends ReactiveCrudRepository<Usr, Integer> {
	@Query("SELECT id, firstname, lastname FROM Usr c WHERE c.lastname = :lastname")
	Flux<Usr> findByLastname(String lastname);
}

UsrController.java

package controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.RequiredArgsConstructor;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import model.Usr;
import repository.UsrRepository;

@RestController
@RequestMapping(path = "/user", produces = "application/hal+json")
@RequiredArgsConstructor
public class UsrController {
	private final UsrRepository usrRepository;
	
	@GetMapping("/all")
	public Flux<Usr> findAll() {
		return usrRepository.findAll();
	}
	
	@GetMapping("/save")
	public Mono<Usr> save() {
		Usr user = new Usr(null, "Lindong", "Wang");
		return usrRepository.save(user);
	}
}

DatabaseConfig.java

package config;

import java.util.Arrays;
import java.util.List;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.r2dbc.core.DatabaseClient;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import model.Usr;
import repository.UsrRepository;

@Configuration
@Slf4j
public class DbConfig {
	@Bean
	public ApplicationRunner initDatabase(DatabaseClient client, UsrRepository usrRepository) {
		List<String> statements = Arrays.asList(
				"DROP TABLE IF EXISTS Usr;", 
				"CREATE TABLE IF NOT EXISTS Usr (id SERIAL PRIMARY KEY, firstname VARCHAR(100) NOT NULL, lastname VARCHAR(100) NOT NULL);");
		statements.forEach(sql -> executeSql(client, sql)
				.doOnSuccess(count -> log.info("Schema created, rows updated: {}", count))
				.doOnError(error -> log.error("got error: {}", error.getMessage(), error))
				.subscribe()
		);
		return args -> getUser().flatMap(usrRepository::save).subscribe(user -> log.info("User saved: {}", user));
	}
	
	private Flux<Usr> getUser() {
		return Flux.just(new Usr(null, "John", "Doe"), new Usr(null, "Jane", "Doe"));
	}
	
	private Mono<Integer> executeSql(DatabaseClient client, String sql) {
		return client.sql(sql).fetch().rowsUpdated();
	}
}

4. 测试代码

在控制台输入:curl localhost:8080/user/all
可以获得返回结果:[{“id”:1,“firstname”:“John”,“lastname”:“Doe”},{“id”:2,“firstname”:“Jane”,“lastname”:“Doe”}]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值