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

r2dbc

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

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

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

此外,我还写了一篇关于使用Spring WebFlux的文章 ,我在引言中提到过。 如果您有兴趣生产完全React式的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用作默认React流类型的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") }}
}

关于此代码,我将提到一件事。 它很可能在没有实际插入或读取某些记录的情况下执行。 但是,当您考虑它时。 这说得通。 React性应用程序旨在异步执行操作,因此该应用程序已开始处理不同线程中的函数调用。 如果不阻塞主线程,这些异步进程可能永远不会完全执行。 因此,此代码中有一些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的内部步骤在单独的线程上运行。

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

结论

总之,由于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

r2dbc

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

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

相关文章

python中布尔类型是特殊的_Python中的特殊方法以及应用详解

前言Python 中的特殊方法主要是为了被解释器调用的&#xff0c;因此应该尽量使用 len(my_object) 而不是 my_object.__len__() 这种写法。在执行 len(my_object) 时&#xff0c;Python 解释器会自行调用 my_object 中实现的 __len__ 方法。除非有大量的元编程存在&#xff0c;直…

IntelliJ IDEA 自动补全变量名称和变量类型(自动补全变量的声明内容)

文章目录varOption EnterOption Command Vvar // 如下声明定义一个字符串变量 String s new String(); // 1 先编写 new String() // 2 在 new String() 后面输入 .var 直接回车&#xff0c;即可得到我们想要的变量了 // 3 上面生成的变量名可能不是我们想要的&#xff0c…

jdk11 jdk12_JDK 12附带紧凑数字格式

jdk11 jdk12JDK 12 Early Access Build 24引入了对紧凑数字格式的支持 。 JDK-8188147&#xff08;紧凑数字格式支持&#xff09;CSR的“摘要”是简单的句子&#xff0c;“添加了对JDK中的紧凑/短数字格式的支持。” 同一CSR还提供了详细的“解决方案”部分&#xff0c;该部分提…

全连接层 时间复杂度_神经网络全连接层(3)

CNN网络基础结构神经网络-全连接层(3)上一回我们聊完了算法&#xff0c;这回我们正式开始写代码。上回在做公式推导的时候&#xff0c;我们实际上只是针对一个数据样本进行推导&#xff0c;而实际中&#xff0c;计算和训练都是一批一批完成的。大多数机器学习训练都有batch的概…

line和spline_探索适用于Apache Spark的Spline Data Tracker和可视化工具(第1部分)

line和spline最近引起我注意的一个有趣且很有希望的开源项目是Spline &#xff0c;它是由Absa维护的Apache Spark数据沿袭跟踪和可视化工具。 该项目由两部分组成&#xff1a;一个在驱动程序上工作的Scala库&#xff0c;该库通过分析Spark执行计划来捕获数据沿袭&#xff0c;以…

MacBook如何快速显示桌面

1.触控板中张开拇指和其它三指 2.通过触发角来快速显示桌面

怎么把word里面虚线变成实线_弱电不会制作cad图,花3分钟看完,只要会用WORD保证你能画出来...

今天我要给你介绍的就是Microsoft Office Visio是Microsoft Office 套件之一。安装Visio之后&#xff0c;可以类比Word的操作方法一样来使用&#xff0c;不过&#xff0c;就是比在Word里画图、修改更方便&#xff0c;功能更强大。特别是在做技术路线图、各种图表的绘图&#xf…

MacBook如何设置分屏浏览的快捷键

MacBook的系统自身无法设置&#xff0c;必须安装第三方软件才能设置&#xff0c;例如&#xff1a;BetterAndBetter、Magnet、BetterSnapTool 等。 BetterAndBetter 的设置&#xff0c;如下图所示&#xff1a;

api自动化测试_API测试和自动化101:基本指南

api自动化测试API代表A pplication P AGC软件我覆盖整个院落。 通常&#xff0c;API用于通过使用任何通信方式来促进两个不同应用程序之间的交互。 在网络上使用API​​时&#xff0c;我们将其称为“ Web服务”。 近年来&#xff0c;API已成为编程的Struts。 与在应用程序中一样…

web.config连接mysql_web.config中配置数据库连接的方式

在网站开发中&#xff0c;数据库操作是经常要用到的操作&#xff0c;ASP.NET中一般做法是在web.config中配置数据库连接代码&#xff0c;然后在程序中调用数据库连接代码&#xff0c;这样做的好处就是当数据库连接代码需要改变的时候&#xff0c;我们只要修改web.config中的数据…

BetterAndBetter(BAB)的使用详解

文章目录多指轻点时防止左键点击规则管理重置全部设置和规则多指轻点时防止左键点击 在正常情况下按下触控板的左键&#xff0c;使用鼠标选择好文本后&#xff0c;松开触控板的左键&#xff0c;就已经退出文本选择模式了&#xff0c;此时移动鼠标应该是不会影响到已经选择的文…

gradle使用maven_使用Gradle – 2019版从Travis可靠发布到Maven Central

gradle使用maven得益于在2018年和2019年末实现的显式登台存储库创建功能集&#xff0c;使您&#xff08;自动&#xff09;从Travis&#xff08;不仅是&#xff09;发布到Maven Central更加可靠。 背景 如果您仅想获取有关如何使工件从Travis发行的信息更可靠的信息&#xff0c…

mysql 事件 day hour_Mysql事件调度器(Event Scheduler)

Mysql中的事件调度器Event Scheduler类似于linux下的crontab计划任务的功能,它是由一个特殊的时间调度线程执行的一、查看当前是否开启了event scheduler三种方法:1) SHOW VARIABLES LIKE ‘event_scheduler’;2) SELECT event_scheduler;3) SHOW PROCESSLIST;(是否有State为&a…

2020年全国儿童青少年总体近视率为52.7%,比上年上升2.5%播

2021年7月13日&#xff0c;国家卫健委召开新闻发布会介绍儿童青少年近视防控和暑期学生健康有关情况。国家卫健委疾控局副局长再那吾东玉山介绍&#xff0c;2020年上半年全民居家抗疫减少了户外活动和放松眼睛的时间&#xff0c;对近视防控工作带来了挑战。为全面评估近视率的情…

精简jdk包_在JDK 12精简数字格式中使用最小分数数字

精简jdk包帖子“ 紧凑数字格式出现在JDK 12中 ”演示了对JDK 12中 NumberFormat的支持&#xff0c;以支持紧凑数字格式 。 该帖子中显示的示例仅使用NumberFormat的实例&#xff0c;这些实例是通过调用NumberFormat的新重载getCompactNumberInstance(-)方法返回的&#xff0c;因…

mysql insert limit_Mysql Limit 调优

建表与插入数据SQL对比基本数据创建表CREATE TABLE student(id int(10) NOT NULL AUTO_INCREMENT,name varchar(25) DEFAULT NULL,age tinyint(2) DEFAULT NULL,live varchar(255) DEFAULT NULL,PRIMARY KEY (id)) ;批量插入1百万条数据DROP PROCEDURE IF EXISTS insert_Stu;DE…

预防近视的方法

推荐的方法里面有角膜塑形镜&#xff0c;也就是OK镜&#xff0c;还有低浓度阿托品、补光仪、离焦软镜、离焦框架眼镜等&#xff0c;阿托品离焦眼镜

spoon java_如何以及为什么使用Spoon分析,生成和转换Java代码

spoon javaSpoon是分析&#xff0c;生成和转换Java代码的工具。 在本文中&#xff0c;我们将看到通过使用以编程方式处理代码的技术可以实现什么。 我认为这些技术不是很为人所知或使用&#xff0c;这很遗憾&#xff0c;因为它们可能非常有用。 谁知道&#xff0c;即使您不想使…

下列支持mysql中文字符_MySQL中文支持问题

0. 本文目的让MySQL支持中文1. 测试环境Windows XP sp2&#xff0c;MySQL Server 5.1&#xff0c;MySQL Administrator 1.2.172. 操作步骤1)修改数据库的默认字符集(开始菜单) - MySQL - MySQL Server 5.1 - MySQL Server Instance Config Wizard&#xff1a;- Reconfigure Ins…

异常(Exception)的学习

1.Throwsable 的两个子类 Exception 和 Error 2.Exception 这是编译期异常&#xff0c;可以捕获处理 3.RuntimeException 表示运行期间的异常&#xff0c;它是 Exception 的子类 4.Error 这是程序错误&#xff0c;不可捕获处理。例如&#xff0c;内存溢出 5.throws 关键字&…