使用Spring Data R2DBC进行异步RDBMS访问

不久之前,发布了JDBC驱动程序的反应型。 称为R2DBC。 它允许将数据异步流传输到已预订的任何端点。 通过将R2DBC之类的反应性驱动程序与Spring WebFlux结合使用,可以编写一个完整的应用程序,以异步方式处理数据的接收和发送。 在本文中,我们将重点介绍数据库。 从连接到数据库,然后最终保存和检索数据。 为此,我们将使用Spring Data。 与所有Spring Data模块一样,它为我们提供了现成的配置。 减少为实现应用程序设置而需要编写的样板代码数量。 最重要的是,它在数据库驱动程序上提供了一层,使执行简单任务变得更加容易,而较困难的任务则减轻了一些痛苦。

对于本文的内容,我正在使用Postgres数据库。 在撰写本文时,仅Postgres,H2和Microsoft SQL Server具有其自己的R2DBC驱动程序实现。

我以前写过两篇有关反应式Spring Data库的文章,一篇关于Mongo ,另一篇关于Cassandra 。 您可能已经注意到,这些数据库都不是RDBMS数据库。 现在有很长一段时间都可以使用其他反应式驱动程序(我将近两年前写了Mongo文章),但是在为RDBMS数据库编写反应式驱动程序时,这仍然是一件很新的事情。 这篇文章将遵循类似的格式。

此外,我还写了一篇关于使用Spring WebFlux的文章 ,我在引言中提到过。 如果您有兴趣生产完全反应式的Web应用程序,请随时查看。

依存关系

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-r2dbc</artifactId><version>1.0.0.M1</version></dependency><dependency><groupId>io.r2dbc</groupId><artifactId>r2dbc-postgresql</artifactId><version>1.0.0.M6</version></dependency><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-core</artifactId></dependency>
</dependencies><repositories><repository><id>repository.spring.milestone</id><name>Spring Milestone Repository</name><url>http://repo.spring.io/milestone</url></repository>
</repositories>

这里有几点要指出。

使用Spring Boot的次数越多,就越会习惯于为您想做的很酷的事情导入单个spring-boot-starter依赖项。 例如,我希望会有spring-boot-starter-r2dbc依赖关系,但不幸的是,没有依赖关系。 然而。 简而言之,该库位于较新的一侧,在编写本文时,它没有自己的Spring Boot模块,该模块包含所需的任何依赖项以及通过自动配置的更快设置。 我确信这些事情会在某个时候出现,并使设置R2DBC驱动程序变得更加容易。

现在,我们将需要手动填写一些额外的依赖项。

此外,R2DBC库仅具有Milestone版本(更多证明是新版本),因此我们需要确保引入Spring Milestone存储库。 当我获得发布版本时,将来可能会需要更新此帖子。

连接到数据库

由于Spring Data为我们做了很多工作,因此唯一需要手动创建的Bean是ConnectionFactory ,其中包含数据库的连接详细信息:

@Configuration
@EnableR2dbcRepositories
class DatabaseConfiguration(@Value("\${spring.data.postgres.host}") private val host: String,@Value("\${spring.data.postgres.port}") private val port: Int,@Value("\${spring.data.postgres.database}") private val database: String,@Value("\${spring.data.postgres.username}") private val username: String,@Value("\${spring.data.postgres.password}") private val password: String
) : AbstractR2dbcConfiguration() {override fun connectionFactory(): ConnectionFactory {return PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder().host(host).port(port).database(database).username(username).password(password).build())}
}

这里首先要注意的是AbstractR2dbcConfiguration的扩展。 此类包含大量不再需要手动创建的Bean。 实现connectionFactory是该类的唯一要求,因为创建DatabaseClient Bean是必需的。 这种结构是Spring Data模块的典型结构,因此在尝试其他结构时会感到非常熟悉。 此外,我希望一旦有自动配置,就可以删除此手动配置,并且可以通过application.properties单独驱动。

我在此处包括了port属性,但是如果您还没有使用Postgres配置,那么可以依靠默认值5432

PostgresqlConnectionFactory定义的四个属性: hostdatabaseusernamepassword是使它正常工作的最低要求。 少了一点,您将在启动过程中遇到异常。

使用此配置,Spring可以连接到正在运行的Postgres实例。

该示例中最后一个值得注意的信息是@EnableR2dbcRepositories的使用。 该注释指示Spring查找扩展Spring的Repository接口的任何存储Repository接口。 这用作检测Spring Data存储库的基本接口。 我们将在下一部分中对此进行更仔细的研究。 从这里获得的主要信息是,您需要使用@EnableR2dbcRepositories批注以充分利用Spring Data的功能。

创建一个Spring数据仓库

如上所述,在本节中,我们将介绍添加Spring Data Repository。 这些存储库是Spring Data的一个不错的功能,这意味着您无需写很多额外的代码即可简单地编写查询。 不幸的是,至少就目前而言,Spring R2DBC无法以与其他Spring Data模块当前相同的方式来推断查询(我肯定会在某个时候添加它)。 这意味着您将需要使用@Query批注并手动编写SQL。 让我们来看看:

@Repository
interface PersonRepository : R2dbcRepository<Person, Int> {@Query("SELECT * FROM people WHERE name = $1")fun findAllByName(name: String): Flux<Person>@Query("SELECT * FROM people WHERE age = $1")fun findAllByAge(age: Int): Flux<Person>
}

该接口扩展了R2dbcRepository 。 这依次扩展了ReactiveCrudRepository ,然后扩展到RepositoryReactiveCrudRepository提供了标准的CRUD功能,据我了解, R2dbcRepository不提供任何额外的功能,而是为更好的情境命名而创建的接口。

R2dbcRepository接受两个通用参数,一个是它作为输入并作为输出产生的实体类。 第二个是主键的类型。 因此,在这种情况下, Person类由PersonRepository管理(有意义),并且Person内部的主键字段是Int

此类中的函数以及ReactiveCrudRepository提供的函数的返回类型为FluxMono (此处未显示)。 这些是Spring用作默认反应流类型的Project Reactor类型。 Flux代表多个元素的流,而Mono则是单个结果。

最后,正如我在示例之前提到的那样,每个函数都使用@Query注释。 语法非常简单,SQL是注释中的字符串。 $1 (用于更多输入的$2$3等)表示输入到函数中的值。 完成此操作后,Spring将处理其余部分,并将输入传递到各自的输入参数中,收集结果并将其映射到存储库的指定实体类。

快速浏览实体

在这里不多说,仅显示PersonRepository使用的Person类。

@Table("people")
data class Person(@Id val id: Int? = null,val name: String,val age: Int
)

实际上,这里有一点需要说明。 id已设置为可为空,并提供默认值null以允许Postgres自身生成下一个合适的值。 如果这不能为空并且提供了一个id值,那么Spring在保存时实际上将尝试运行更新而不是插入操作。 还有其他解决方法,但是我认为这已经足够了。

该实体将映射到下面定义的people表:

CREATE TABLE people (id SERIAL PRIMARY KEY, name VARCHAR NOT NULL, age INTEGER NOT NULL
);

看到一切都在行动

现在让我们看看它实际上在做什么。 下面是一些插入一些记录并以几种不同方式检索它们的代码:

@SpringBootApplication
class Application : CommandLineRunner {@Autowiredprivate lateinit var personRepository: PersonRepositoryoverride fun run(vararg args: String?) {personRepository.saveAll(listOf(Person(name = "Dan Newton", age = 25),Person(name = "Laura So", age = 23))).log().subscribe()personRepository.findAll().subscribe { log.info("findAll - $it") }personRepository.findAllById(Mono.just(1)).subscribe { log.info("findAllById - $it") }personRepository.findAllByName("Laura So").subscribe { log.info("findAllByName - $it") }personRepository.findAllByAge(25).subscribe { log.info("findAllByAge - $it") }}
}

关于此代码,我将提到一件事。 它很可能在没有实际插入或读取某些记录的情况下执行。 但是,当您考虑时。 这说得通。 反应性应用程序旨在异步执行操作,因此该应用程序已开始处理不同线程中的函数调用。 如果不阻塞主线程,这些异步进程可能永远不会完全执行。 出于这个原因,此代码中有一些Thread.sleep调用,但我从示例中删除了它们,以使所有内容保持整洁。

运行上面的代码的输出如下所示:

2019-02-11 09:04:52.294  INFO 13226 --- [           main] reactor.Flux.ConcatMap.1                 : onSubscribe(FluxConcatMap.ConcatMapImmediate)
2019-02-11 09:04:52.295  INFO 13226 --- [           main] reactor.Flux.ConcatMap.1                 : request(unbounded)
2019-02-11 09:04:52.572  INFO 13226 --- [actor-tcp-nio-1] reactor.Flux.ConcatMap.1                 : onNext(Person(id=35, name=Dan Newton, age=25))
2019-02-11 09:04:52.591  INFO 13226 --- [actor-tcp-nio-1] reactor.Flux.ConcatMap.1                 : onNext(Person(id=36, name=Laura So, age=23))
2019-02-11 09:04:52.591  INFO 13226 --- [actor-tcp-nio-1] reactor.Flux.ConcatMap.1                 : onComplete()
2019-02-11 09:04:54.472  INFO 13226 --- [actor-tcp-nio-2] com.lankydanblog.tutorial.Application    : findAll - Person(id=35, name=Dan Newton, age=25)
2019-02-11 09:04:54.473  INFO 13226 --- [actor-tcp-nio-2] com.lankydanblog.tutorial.Application    : findAll - Person(id=36, name=Laura So, age=23)
2019-02-11 09:04:54.512  INFO 13226 --- [actor-tcp-nio-4] com.lankydanblog.tutorial.Application    : findAllByName - Person(id=36, name=Laura So, age=23)
2019-02-11 09:04:54.524  INFO 13226 --- [actor-tcp-nio-5] com.lankydanblog.tutorial.Application    : findAllByAge - Person(id=35, name=Dan Newton, age=25)

这里有一些要注意的地方:

  • onSubscriberequest发生在调用Flux的主线程上。 仅saveAll输出此内容,因为它已包含log功能。 将其添加到其他调用中将导致记录到主线程的结果相同。
  • subscription函数中包含的执行和Flux的内部步骤在单独的线程上运行。

这与在实际应用程序中如何使用反应流的真实表示不尽相同,但希望能演示如何使用它们,并对它们的执行方式提供一些见解。

结论

总之,由于R2DBC驱动程序和Spring Data在顶部建立了一层,使所有内容变得更加整洁,因此Reactive Streams进入了某些RDBMS数据库。 通过使用Spring Data R2DBC,我们能够创建与数据库的连接并开始查询它,而无需太多代码。 尽管Spring已经为我们做了大量工作,但它可能会做更多的事情。 当前,它不具有Spring Boot自动配置支持。 这有点烦人。 但是,我相信有人很快就会做起来并使所有事情变得比现在更好。

这篇文章中使用的代码可以在我的GitHub上找到 。

翻译自: https://www.javacodegeeks.com/2019/02/asynchronous-rdbms-access-spring-r2dbc.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/345588.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【渝粤题库】国家开放大学2021春3935理工英语2题目

试卷代号&#xff1a;3935 2021年春季学期期末统一考试 理工英语2 试题 2021年7月注 意 事 项 一、将你的学号、姓名及分校&#xff08;工作站&#xff09;名称填写雀答题纸的规定栏内。考试结束后&#xff0c;把试卷和答题纸放在桌上。试卷和答题纸均不得带出考场。监考人…

Filtration, σ-algebras

1. Filtration filtration在钱敏平老师和龚光鲁老师的《随机过程论》中直接称其为非降的KaTeX parse error: Undefined control sequence: \sigmma at position 1: \̲s̲i̲g̲m̲m̲a̲代数族。如图。 一般叫σ\sigmaσ-代数流或σ\sigmaσ-域流 在鞅论中的花体FtF_tFt​&…

【渝粤题库】国家开放大学2021春4988电子政务概论题目

试卷代号&#xff1a;4988 2021年春季学期期末统一考试 电子政务概论 试题&#xff08;开卷&#xff09; 2021年7月 注意事项 一、将你的学号、姓名及分校&#xff08;工作站&#xff09;名称填写在答题纸的规定栏内。考试 结束后&#xff0c;把试卷和答题纸放在桌上。试卷和答…

gradle 命令行_Gradle命令行便利

gradle 命令行在我的《用Gradle构建Java的gradle tasks 》一文中&#xff0c;我简要提到了使用Gradle的“ gradle tasks ”命令来查看特定Gradle构建的可用任务。 在这篇文章中&#xff0c;我将对这一简短提及进行更多的扩展&#xff0c;并查看一些相关的Gradle命令行便利。 Gr…

【渝粤题库】广东开放大学 java web开发技术 形成性考核

题库查询系统 选择题 题目&#xff1a;当多个用户请求同一个JSP页面时&#xff0c;Tomcat服务器为每个客户启动一个_____。 题目&#xff1a;以下_____不是JSP运行所必须的条件。 题目&#xff1a;Tomcat服务器的默认端口为_____。 题目&#xff1a;如果想在tomcat服务器启动时…

【渝粤题库】广东开放大学 实用文写作 形成性考核

选择题 题目&#xff1a; 《关于厂进口SD6型自动车床的请示》&#xff0c;作者应是&#xff1a;( ) 选择一项&#xff1a; 题目&#xff1a; 请示可以一文多事。 选择一项&#xff1a; 题目&#xff1a; 除批转法规性文件外&#xff0c;通知的标题中一般不含书名号。&#x…

怎样更好地理解并记忆泰勒展开式

本段的核心思想是仿造。当我们想要仿造一个东西的时候&#xff0c;无形之中都会按照上文提到的思路&#xff0c;即先保证大体上相似&#xff0c;再保证局部相似&#xff0c;再保证细节相似&#xff0c;再保证更细微的地方相似……不断地细化下去&#xff0c;无穷次细化以后&…

【渝粤题库】广东开放大学 标准法律法规 形成性考核

​&#x1f449;关注我,看答案&#x1f448; 选择题 题目&#xff1a;狭义的立法程序仅指国家最高( )在制定、修改、补充、废止规范性文件过程中的工作方法、步骤和次序。 题目&#xff1a;行政法规是国务院制定、修改的有关&#xff08; &#xff09;和管理行政事务事项的规范…

新的DMN编辑器预览

Workbench 7.13.0.Final于10月16日星期二发布&#xff0c;此版本带来了许多有趣的功能和重要的修复程序。 亮点之一是作为技术预览功能的新DMN编辑器&#xff0c;该功能仍在开发中&#xff0c;但您可以开始使用。 在本文中&#xff0c;您将学习如何启用DMN编辑器预览&#xff…

【渝粤题库】广东开放大学 面向对象方法精粹 形成性考核

选择题 题目&#xff1a; 单选 可行性分析研究的主要目的是 题目&#xff1a; &#xff08;&#xff09;指的是一个软件结构内&#xff0c;不同模块之间互联的紧密程度。 题目&#xff1a; 4 、&#xff08;&#xff09;衡量一个模块内各个元素彼此结合的紧密程度。 题目&#…

junit junit_JUnit理论简介

junit junit您读过数学理论吗&#xff1f; 它通常读取如下内容&#xff1a; 对于所有a&#xff0c;b> 0满足以下条件&#xff1a;a b> a和a b> b 通常&#xff0c;这些语句更难以理解。 这种陈述有一些有趣的地方&#xff1a;它适用于相当大&#xff08;在这种情…

指数矩阵(exponential matrix)

类似于指数ex……e^x……ex……的本质是一种近似&#xff0c;eAt……e^{At}……eAt……是同样原理。 http://www.mashangxue123.com/%E7%BA%BF%E6%80%A7%E4%BB%A3%E6%95%B0/1756604500.html

【渝粤题库】陕西师范大学151210 成本会计作业 (专升本)

《成本会计【专升本】》作业 一、单选题 1.从现行企业会计制度的有关规定出发&#xff0c;成本会计的对象是&#xff08; &#xff09;。 A各项期间费用的支出及归集过程 B产品生产成本的形成过程 C诸会计要素的增减变动 D企业生产经营过程中发生的生产经营业务成本和期间费用 …

【渝粤题库】陕西师范大学152206领导科学 作业(高起专、专升本)

一、单项选择题 1、马克思主义领导科学的基本问题是&#xff08; &#xff09;。 A、正确处理领导者与客观环境的关系 B、正确处理被领导者与客观环境的关系 C、正确处理领导与学习的关系 D、正确处理领导者与被领导者的关系 2、著名的军事家孙子说&#xff0c;“将者&#xff…

Jenkins在AWS上(第1部分)

这是我对PEAT UK播客的逐字记录&#xff1a; 你好&#xff0c;再一次到另一个热点。 我叫Peter Pilgrim。 我曾经是DevOps专家&#xff0c;欢迎观看另一集。 这是11 Jenkins n AWS的第一部分&#xff0c;我是一名平台工程师&#xff0c;并且是Java Champion。 在本集中&…

【渝粤题库】国家开放大学2021春2227物业设备设施管理题目

试卷代号&#xff1a;2227 2021年春季学期期末统一考试 物业设备设施管理 试题&#xff08;开卷&#xff09; 2021年7月 一、单项选择题&#xff08;下列每题中的四个选择项中只有一个是正确的&#xff0c;请将其代号填在括号内。每题2分&#xff0c;共30分&#xff09; 1.设备…

Boole‘s,Doob‘s inequality,中心极限定理Central Limit Theorem,Kolmogorov extension theorem, Lebesgue‘s domin

1. Boole’s inequality In probability theory, Boole’s inequality, also known as the union bound, says that for any finite or countable set of events, the probability that at least one of the events happens is no greater than the sum of the probabilities …

【渝粤题库】国家开放大学2021春2302供应链管理题目

试卷代号&#xff1a;2302 2021年春季学期期末统一考试 供应链管理 试题 2021年7月 .一、单项选择题&#xff08;每小题2分&#xff0c;共20分&#xff0c;将正确答案填入括号内&#xff09; 1.不同的行业&#xff0c;不同的企业&#xff0c;其供应链形态一般( )。 A.相同 B.不…

【渝粤题库】国家开放大学2021春2320物流管理定量分析方法题目

试卷代号&#xff1a; 2320 2021年春季学期期末统一考试 物流管理定量分析方法 试题 2021年7月 物流管理定量分析方法 试题 2021年1月 MATLAB的常用标准函数和命令函数&#xff1a; 一、单项选择题&#xff08;每小题4分&#xff0c;共20分&#xff09; 1.若某物资的总供应量…