SpringBoot 官方文档示例:(68)使用R2DBC操作Postgresql

一、在Postgresql中创建表

CREATE TABLE product
(
    id   SERIAL PRIMARY KEY,
		price numeric,
		description varchar
)

二、创建Spring boot 项目,添加依赖,完整依赖类似如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.edu.tju</groupId>
    <artifactId>springboot2023</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-r2dbc</artifactId>
        </dependency>

        <dependency>
            <groupId>io.r2dbc</groupId>
            <artifactId>r2dbc-postgresql</artifactId>
            <version>0.8.13.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
        </dependency>

    </dependencies>

</project>

三、在application.properties配置数据库连接:

spring.r2dbc.url=r2dbc:postgresql://localhost:5432/test
spring.r2dbc.username=postgres
spring.r2dbc.password=root
spring.datasource.driver-class-name=org.postgresql.Driver

也可以使用配置类来配置数据库:

package cn.edu.tju.config;

import io.r2dbc.spi.ConnectionFactories;
import io.r2dbc.spi.ConnectionFactory;
import io.r2dbc.spi.ConnectionFactoryOptions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import static io.r2dbc.spi.ConnectionFactoryOptions.DATABASE;
import static io.r2dbc.spi.ConnectionFactoryOptions.DRIVER;
import static io.r2dbc.spi.ConnectionFactoryOptions.HOST;
import static io.r2dbc.spi.ConnectionFactoryOptions.PASSWORD;
import static io.r2dbc.spi.ConnectionFactoryOptions.PORT;
import static io.r2dbc.spi.ConnectionFactoryOptions.USER;

@Configuration
public class R2DBCConfig {

    @Bean
    public ConnectionFactory connectionFactory() {
        return ConnectionFactories.get(
                ConnectionFactoryOptions.builder()
                        .option(DRIVER, "postgresql")
                        .option(HOST, "localhost")
                        .option(PORT, 5432)
                        .option(USER, "postgres")
                        .option(PASSWORD, "root")
                        .option(DATABASE, "test")
                        .build());
    }
}

四、创建相关类

实体类

package cn.edu.tju.domain;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.domain.Persistable;


public class Product  implements Persistable<Integer> {
    @Id
    private Integer id;
    private String description;
    private Double price;

    public Integer getId() {
        return id;
    }



    public void setId(Integer id) {
        this.id = id;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    @Transient
    public boolean isNew() {
        return newFlag || id == null;
    }

    @Transient
    private boolean newFlag;
    public Product setNewFlag() {
        newFlag = true;
        return this;
    }
}


Repository类

package cn.edu.tju.repository;

import cn.edu.tju.domain.Product;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;

import org.springframework.stereotype.Repository;

@Repository
public interface ProductRepository extends ReactiveCrudRepository<Product, Integer> {
}


Service类

package cn.edu.tju.service;

import cn.edu.tju.repository.ProductRepository;
import cn.edu.tju.domain.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Service
public class ProductService {

    @Autowired
    private ProductRepository repository;

    @Transactional
    public Mono<Product> createProduct(Product product) {
        return repository.save(product);
    }

    @Transactional
    public Mono<Product> deleteProduct(int id) {
        return repository
                .findById(id)
                .flatMap(p -> repository.deleteById(p.getId()).thenReturn(p));
    }


    @Transactional
    public Mono<Product> updateProduct(Product product) {
        return repository.findById(product.getId())
                .flatMap(p -> {
                    p.setDescription(product.getDescription());
                    p.setPrice(product.getPrice());
                    return repository.save(p);
                });
    }

    public Flux<Product> getProductList() {
        return repository.findAll();
    }





}

最后创建contoller类

package cn.edu.tju.controller;

import cn.edu.tju.service.ProductService;
import cn.edu.tju.domain.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * The traditional way to handle the rest endpoints
 */

@RestController
@RequestMapping("/product")
public class ProductController {

    @Autowired
    private ProductService productService;

    @PostMapping("/add")
    public Mono<Product> add(@RequestBody Product product) {
        return productService.createProduct(product);
    }

    @DeleteMapping("/{id}")
    public Mono<Product> deleteProduct(@PathVariable int id) {
        return productService.deleteProduct(id);
    }
    @PostMapping("/update")
    public Mono<Product> updateProduct(@RequestBody Product product) {
        return productService.updateProduct(product);
    }

    @GetMapping("/list")
    public Flux<Product> listProduct() {
        return productService.getProductList();
    }

}

或者用RouterFunction

Handler类

package cn.edu.tju.handler;

import cn.edu.tju.domain.Product;
import cn.edu.tju.service.ProductService;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.URI;

@Component
public class ProductHandler {

    @Autowired
    private ProductService productService;

    public Mono<ServerResponse> create(ServerRequest request) {
        Flux<Product> flux = request
                .bodyToFlux(Product.class)
                .flatMap(p -> productService.createProduct(p));
        return writeResponse(flux);
    }

    public Mono<ServerResponse> deleteById(ServerRequest request) {
        return readResponse(productService.deleteProduct(id(request)));
    }

    public Mono<ServerResponse> update(ServerRequest request) {
        Flux<Product> flux = request
                .bodyToFlux(Product.class)
                .flatMap(p -> productService.updateProduct(p));
        return writeResponse(flux);
    }



    public Mono<ServerResponse> list(ServerRequest request) {
        return readResponse(productService.getProductList());
    }



    private static Mono<ServerResponse> readResponse(Publisher<Product> products) {
        return ServerResponse
                .ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(products, Product.class);
    }

    private static Mono<ServerResponse> writeResponse(Publisher<Product> product) {
        return Mono
                .from(product)
                .flatMap(p -> ServerResponse
                        .created(URI.create("/product"))
                        .contentType(MediaType.APPLICATION_JSON)
                        .build()
                );
    }

    private static int id(ServerRequest request) {
        return Integer.parseInt(request.pathVariable("id"));
    }
}
package cn.edu.tju.config;

import cn.edu.tju.handler.ProductHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;

import static org.springframework.web.reactive.function.server.RequestPredicates.DELETE;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;

@Configuration
public class EndpointConfig {

    private static String PRODUCT = "/product";

    @Bean
    RouterFunction<ServerResponse> routes(ProductHandler handler) {
        return route(POST(PRODUCT+"/add"), handler::create)
                .andRoute(DELETE(PRODUCT + "/{id}"), handler::deleteById)
                .andRoute(POST(PRODUCT+"/update" ), handler::update)
                .andRoute(GET(PRODUCT+"/list"), handler::list);
    }
}

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

也可以使用DatabaseClient类来操作数据库

    @Autowired
    private DatabaseClient databaseClient;

@GetMapping("/test")
public Flux<Map<String, Object>> someMethod() {
    return this.databaseClient.sql("select * from product").fetch().all();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值