转载

使用Spring Boot反应式R2DBC实现PostgreSQL的CRUD操作源码 - Rajesh

在本文中,让我们看一下用于Postgres的Spring-Data-R2DBC驱动程序,以进行响应式CRUD操作。

完整的代码 在这里

使用Spring Boot版本2.3.1,JDK版本14和Gradle作为构建工具。如果您不熟悉Gradle,则可以自由选择Maven作为构建工具。

首先,R2DBC项目是最近的。目前,只有Postgres,MSSQL和H2具有R2DBC驱动程序。此外,我们不能将其与所有Spring Boot功能一起使用。因此,我们需要手动添加一些步骤。

在您的Postgres数据库中创建一个表。

CREATE TABLE product
(
id integer,
description character varying(255),
price numeric,
PRIMARY KEY (id)
);

数据实体:

@Data
@ToString
<b>public</b> <b>class</b> Product implements Persistable<Integer> {

    @Id
    <b>private</b> Integer id;
    <b>private</b> String description;
    <b>private</b> Double price;

    @Transient
    <b>private</b> <b>boolean</b> newProduct;

    @Override
    @Transient
    <b>public</b> <b>boolean</b> isNew() {
        <b>return</b> <b>this</b>.newProduct || id == <b>null</b>;
    }

    <b>public</b> Product setAsNew() {
        <b>this</b>.newProduct = <b>true</b>;
        <b>return</b> <b>this</b>;
    }
}

记住这里我们正在实现Persistable接口。根据您提供的@Id,持久库确定该行是新行还是应该存在。如果您的实体实施Persistable,使用save(…)保存结果时,根据isNew()来确定是否实现数据库的INSERT或UPDATE。

使用数据库时,我们需要一个连接工厂。因此,当然,R2DBC也需要同样的东西。

因此,我们现在将添加详细信息以连接到我们的实例:

@Configuration
<b>public</b> <b>class</b> R2DBCConfig {

    @Bean
    <b>public</b> ConnectionFactory connectionFactory() {
        <b>return</b> ConnectionFactories.get(
                ConnectionFactoryOptions.builder()
                        .option(DRIVER, <font>"postgresql"</font><font>)
                        .option(HOST, </font><font>"localhost"</font><font>)
                        .option(PORT, 5432)
                        .option(USER, </font><font>"postgres"</font><font>)
                        .option(PASSWORD, </font><font>"******"</font><font>)
                        .option(DATABASE, </font><font>"postgres"</font><font>)
                        .option(MAX_SIZE, 40)
                        .build());
    }
}
</font>

存储库负责持久化实体和值类型。他们为客户提供了一个简单的模型,用于获取持久性对象并管理其生命周期。它们使应用程序和领域设计与持久性技术和策略选择脱钩。他们还传达有关对象访问的设计决策。最后,它们允许用虚拟实现轻松替换实现,是测试的理想选择。Spring Data的存储库通过接口定义支持所有这些目标,这些定义的实现是在框架启动时由框架创建的。

创建一个Spring Data存储库:

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

Spring Framework 5改变了一切。Spring Framework 5假定使用Java 8基线,并具有lambda和无限的功能性可能性!

我们在反应式Web应用程序中所做的许多事情都使其具有函数性编程风格。Spring Framework 5首次推出了一种新的功能性反应式编程模型,该模型与Spring WebFlux中的控制器风格的编程模型相似。这个新的编程模型仅在Spring WebFlux中可用。

@Configuration
<b>public</b> <b>class</b> ProductsEndpointConfig {

    <b>private</b> <b>static</b> <b>final</b> String PRODUCT = <font>"/product"</font><font>;

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

Spring WebFlux提供了一个DSL,用于描述如何匹配传入的请求。GET("/product")让RequestPredicate与通过GET方法到URI /product的HTTP 方法请求匹配。您可以组合RequestPredicate:.and(RequestPredicate),.not(RequestPredicate)或.or(RequestPredicate)。

匹配请求后,HandlerFunction<ServerResponse>被调用来产生响应。让我们看一下相应的处理程序对象。

@Component
<b>public</b> <b>class</b> ProductHandler {

    <b>final</b> ProductService productService;

    <b>public</b> ProductHandler(ProductService productService) {
        <b>this</b>.productService = productService;
    }

    <b>public</b> Mono<ServerResponse> create(ServerRequest request) {
        Flux<Product> flux = request
                .bodyToFlux(Product.<b>class</b>)
                .flatMap(toWrite -> <b>this</b>.productService.updateProduct(toWrite));
        <b>return</b> defaultWriteResponse(flux);
    }

    <b>public</b> Mono<ServerResponse> all(ServerRequest r) {
        <b>return</b> defaultReadResponse(<b>this</b>.productService.getAllProducts());
    }

    <b>public</b> Mono<ServerResponse> deleteById(ServerRequest r) {
        <b>return</b> defaultReadResponse(<b>this</b>.productService.delete(id(r)));
    }

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

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

    <b>private</b> <b>static</b> <b>int</b> id(ServerRequest r) {
        <b>return</b> Integer.parseInt(r.pathVariable(</font><font>"id"</font><font>));
    }
}
</font>

主程序入口:

@SpringBootApplication
@EnableR2dbcRepositories
<b>public</b> <b>class</b> DemoReactiveRdbmsApplication {

    <b>public</b> <b>static</b> <b>void</b> main(String[] args) {

        SpringApplication.run(DemoReactiveRdbmsApplication.<b>class</b>, args);
    }

}

总而言之,R2DBC仍处于早期阶段。试图创建一个SPI,该SPI将为SQL数据库定义一个响应式API。当与 Spring WebFlux 一起使用时,R2DBC允许我们编写一个应用程序,该应用程序从顶部一直到数据库一直异步处理数据。

完整的代码 在这里

原文  https://www.jdon.com/54451
正文到此结束
Loading...