R2DBC-响应式数据库

简单查询

基于全异步,响应式,消息驱动
用法:
1.导入驱动:导入连接池(r2dbc-pool),导入驱动(r2dbc-mysql)
2. 使用驱动提供的api操作
pom.xml

<properties><r2dbc-mysql.version>1.0.5</r2dbc-mysql.version>
</properties><dependencies><dependency><groupId>io.asyncer</groupId><artifactId>r2dbc-mysql</artifactId><version>${r2dbc-mysql.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

单元测试

    @Testpublic void testGetConnection() throws Exception{//1.获取连接工厂MySqlConnectionConfiguration config = MySqlConnectionConfiguration.builder().host("123.57.132.54").username("root").password("zyl000419").database("index_demo").build();MySqlConnectionFactory factory = MySqlConnectionFactory.from(config);//2.获取到连接,发送sqlMono.from(factory.create()).flatMapMany(connection ->connection.createStatement("SELECT * FROM t_author WHERE id = ?id").bind("id",1L).execute())//每一个连接会产生很多数据(result).flatMap(result -> {return result.map(readable -> {Long id = readable.get("id", Long.class);String name = readable.get("name", String.class);return new Author(id,name);});}).subscribe(System.out::println);System.in.read();}

参数赋值
在这里插入图片描述

spring data r2dbc-整合与自动配置

SpringBoot对r2dbc自动配置
R2dbcAutoConfiguration:主要配置连接工厂,连接池
R2dbcDataAutoConfiguration:
r2dbcEntityTemplate:操作数据库的响应式客户端,提供crud Api数据类型映射关系,转换器
自定义R2dbcCustomConversions转换器组件
数据类型 int -> integer; varchar->string
R2dbcRepositoriesAutoConfiguration:开启springboot声明式接口方式的crud
spring data 提供了基础的crud接口,不用写任何实现的情况下,可以直接具有crud功能
R2dbcTransactionManager:事物管理

导入相关依赖

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

编写application.yml配置
调整日志级别,打印sql语句

spring:r2dbc:url: r2dbc:mysql://your_host:3306username: rootpassword: your_passwordname: your_database
logging:level:org.springframework.r2dbc: debug

database client & r2dbcEntityTemplate api

创建数据库映射实体

@Data
@AllArgsConstructor
@NoArgsConstructor
@Table("t_author")
public class Author {private Long id;private String name;}

R2dbcEntityTemplate: crudApi,join操作不好做

    @Autowiredprivate R2dbcEntityTemplate template;@Testpublic void testR2dbcEntityTemplate() throws Exception{//1.构造查询条件Criteria criteria = Criteria.empty().and("id").is(1L).and("name").is("zyl");//2.封装为查询对象Query query = Query.query(criteria);template.select(query, Author.class).subscribe(System.out::println);System.in.read();}

DatabaseClient:数据库客户端,贴近底层,join操作好做

    @Autowiredprivate DatabaseClient databaseClient;@Testpublic void testJoin() throws IOException {databaseClient.sql("SELECT  * FROM t_author WHERE id = ?id").bind("id",1L).fetch().all().map(map -> {String id = String.valueOf(map.get("id"));String name = String.valueOf(map.get("name"));return new Author(Long.valueOf(id), name);}).subscribe(System.out::println);System.in.read();}

spring data r2dbc

开启r2dbc仓库功能,jpa

@EnableR2dbcRepositories
@Configuration
public class R2dbcConfig {}

1.写Repositories接口,默认继承一些crud方法
QBC: Query By Ctiteric
QBE: Query By Example

@Repository
public interface AuthorRepositories extends R2dbcRepository<Author,Long> {}

测试:
复杂调价查询:
1.QBE Api(不推荐)
2.自定义方法
3.自定义sql
repositeries起名有提示,按sql起名

@Repository
public interface AuthorRepositories extends R2dbcRepository<Author,Long> {/*** where id in ? and name like ?*/Flux<Author> findAllByIdInAndNameLike(Collection<Long> ids, String name);
}

测试复杂查询

    @Testpublic void testRepositories() throws IOException {authorRepositories.findAll().subscribe(System.out::println);authorRepositories.findAllByIdInAndNameLike(List.of(1L),"z%").subscribe(System.out::println);System.in.read();}

控制台打印sql

SELECT t_author.id, t_author.name 
FROM t_author 
WHERE t_author.id IN (?) AND (t_author.name LIKE ?)

缺点:仅限单表crud
测试多表复杂查询
自定义注解@Query(),指定sql语句
1-1查询:一个图书有一个作者
1-n查询:一个作者写了多本图书
实体类Book

@Data
@Table("t_book")
public class Book {@Idprivate Long id;private String title;private Long authorId;private LocalDateTime publishTime;}

repositorues

@Repository
public interface BookRepositories extends R2dbcRepository<Book,Long> {@Query("SELECT book.title,author.name " +"FROM index_demo.t_book book " +"LEFT JOIN index_demo.t_author author " +"ON book.author_id = author.id " +"WHERE book.id = :bookId")Mono<Book> findBookAndAuthor(Long bookId);
}

绑定查询参数:
在这里插入图片描述
自定义结果转换器

@ReadingConverter//读取数据库数据时,把row->book
public class BookConverter implements Converter<Row, Book> {@Overridepublic Book convert(Row source) {if (ObjectUtils.isEmpty(source)) {return new Book();}String title = source.get("title", String.class);String authorName = source.get("name", String.class);Book book = new Book();Author author = new Author();author.setName(authorName);book.setAuthor(author);book.setTitle(title);return book;}
}

配置自定义类型转换器

@EnableR2dbcRepositories
@Configuration
public class R2dbcConfig {/*** 将自己定义的转换器加入进去*/@Bean@ConditionalOnMissingBeanpublic R2dbcCustomConversions conversions () {return R2dbcCustomConversions.of(MySqlDialect.INSTANCE,new BookConverter());}}

测试

    @Testpublic void testQueryMulti() throws Exception{bookRepositories.findBookAndAuthor(1L).subscribe(System.out::println);System.in.read();}

总结:
1.spring data R2DBC 基础的CRUD用R2dbcRepository 提供好了
2.自定义复杂的sql(单表):@Query()
3.多表查询复杂结果集合:DatabaseClient自定义sql,自定义结果封装
@Query+自定义converter实现结果封装
自定义转换器问题:对以前crud产生影响
Converter<Row,Book>:把数据库每一行row,转换成book
工作时机:spring data发现方法签名只要是返回Book,利用自定义转换器工作
所有对Book结果封装都使用转换器,包括单表查询
解决方法1:新VO+新的Repositories+自定义类型转换器
BookauthorVO

@Data
public class BookAuthorVO {private Long id;private String title;private Long authorId;private LocalDateTime publishTime;private Author author;//每一本书有唯一作者
}

自定义BookAuthorRepositories

@Repository
public interface BookAuthorRepositories extends R2dbcRepository<BookAuthorVO,Long> {@Query("SELECT book.title,author.name " +"FROM index_demo.t_book book " +"LEFT JOIN index_demo.t_author author " +"ON book.author_id = author.id " +"WHERE book.id = :bookId")Mono<Book> findBookAndAuthor(@Param("bookId")Long bookId);
}

自定义BookAuthor转换器

@ReadingConverter//读取数据库数据时,把row->book
public class BookAuthorConverter implements Converter<Row, BookAuthorVO> {@Overridepublic BookAuthorVO convert(Row source) {if (ObjectUtils.isEmpty(source)) {return new BookAuthorVO();}String title = source.get("title", String.class);String authorName = source.get("name", String.class);BookAuthorVO book = new BookAuthorVO();Author author = new Author();author.setName(authorName);book.setAuthor(author);book.setTitle(title);return book;}
}

解决方法2:自定义转换器中增加判断
source.getMetaData.contains(“”)
让converter兼容更多表结构(推荐!!!)

@ReadingConverter//读取数据库数据时,把row->book
public class BookAuthorConverter implements Converter<Row, BookAuthorVO> {@Overridepublic BookAuthorVO convert(Row source) {if (ObjectUtils.isEmpty(source)) {return new BookAuthorVO();}String title = source.get("title", String.class);BookAuthorVO book = new BookAuthorVO();book.setTitle(title);if (source.getMetadata().contains("name")) {String authorName = source.get("name", String.class);Author author = new Author();author.setName(authorName);book.setAuthor(author);}return book;}
}

经验:
1-1/1-n都需要自定义结果集
spring data R2dbc:自定义converter指定结果封装
mybatis:自定义resultMap标签来封装

BufferUntilChanged操作

如果下一个判定值,比起上一个发生了变化,就开一个新buffer保存
如果没有变化,就保存到原buffer中
前提:数据已经提前排好序
groupBy:允许乱序
作者有很多图书. 1:n
sql

SELECT author.name,author.id,book.title
FROM index_demo.t_author author
LEFT JOIN index_demo.t_book book
ON author.id = book.author_id
WHERE author.id = 1;

测试

    @Testpublic void testAuthorBookTest() throws Exception {databaseClient.sql("SELECT author.name,author.id,book.title " +"FROM index_demo.t_author author " +"LEFT JOIN index_demo.t_book book " +"ON author.id = book.author_id " +"WHERE author.id = ?id").bind("id", 1L).fetch().all().bufferUntilChanged(rowMap -> Long.parseLong(String.valueOf(rowMap.get("id"))))//id发生变化,重新分组,若是对象比较,需重写equals()方法.map(list -> {if (CollectionUtils.isEmpty(list)) {return Collections.emptyList();}List<Book> bookList = list.stream().map(item -> {String title = String.valueOf(item.get("title"));return Book.builder().title(title).build();}).toList();return Author.builder().id(Long.valueOf(String.valueOf(list.get(0).get("id")))).name(String.valueOf(list.get(0).get("name"))).bookList(bookList);}).subscribe(System.out::println);System.in.read();}

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

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

相关文章

实验:MySQL 客户端SocketTimeout 抓包分析

实验准备 服务端环境准备 服务器信息 阿里云 99 大洋白嫖机 $ cat /proc/version Linux version 5.15.0-83-generic (builddlcy02-amd64-027) (gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #92-Ubuntu SMP Mon Aug 14 09:30:42 UT…

Rocky Linux 8.9 安装图解

风险告知 本人及本篇博文不为任何人及任何行为的任何风险承担责任&#xff0c;图解仅供参考&#xff0c;请悉知&#xff01;本次安装图解是在一个全新的演示环境下进行的&#xff0c;演示环境中没有任何有价值的数据&#xff0c;但这并不代表摆在你面前的环境也是如此。生产环境…

《WebKit 技术内幕》学习之七(2): 渲染基础

2 网页层次和RenderLayer树 2.1 层次和RenderLayer对象 前面章节介绍了网页的层次结构&#xff0c;也就是说网页是可以分层的&#xff0c;这有两点原因&#xff0c;一是为了方便网页开发者开发网页并设置网页的层次&#xff0c;二是为了WebKit处理上的便利&#xff0c;也就是…

【表情识别阅读笔记】Towards Semi-Supervised Deep FER with An Adaptive Confidence Margin

论文名&#xff1a; Towards Semi-Supervised Deep Facial Expression Recognition with An Adaptive Confidence Margin 论文来源&#xff1a; CVPR 发表时间&#xff1a; 2022-04 研究背景&#xff1a; 对大量图片或视频进行手工标注表情是一件极其繁琐的事情&#xff0c;因此…

TCP高并发服务器简介(select、poll、epoll实现与区别)

select、poll、epoll三者的实现&#xff1a; select实现TCP高并发服务器的流程&#xff1a; 一、创建套接字&#xff08;socket函数&#xff09;&#xff1a;二、填充服务器的网络信息结构体&#xff1a;三、套接字和服务器的网络信息结构体进行绑定&#xff08;bind函数&…

2024 前端高频面试题之 HTML/CSS 篇

【前言】随着市场的逐渐恶劣&#xff0c;通过总结面试题的方式来帮助更多的coder&#xff0c;也是记录自己的学习过程&#xff0c;温故而知新。欢迎各位同胞大大点评补充~ 前端面试题之 HTML/CSS 篇 1、HTML 语义化&#xff1f;2、块级元素&内联样式3、盒子模型的理解&…

qml 2.8 布局练习

GreenSquare.qml import QtQuickRectangle {width: 100height: 100color: greenborder.color: Qt.lighter(color) } BlueSquare.qml import QtQuickRectangle {color: bluewidth: 50height: 50border.color: Qt.lighter(color)property alias text: label.text //将text开…

linux C语言socket函数send

在Linux中&#xff0c;使用C语言进行网络编程时&#xff0c;send函数是用于发送数据到已连接的套接字的重要函数之一。它通常用于TCP连接&#xff0c;但也可以用于UDP&#xff08;尽管对于UDP&#xff0c;通常更推荐使用sendto&#xff0c;因为它允许你指定目标地址和端口&…

Git学习笔记(第8章):IEAD实现GitHub操作(VSCode)

目录 8.1 VSCode登录GitHub账号 8.2 创建远程库 8.3 本地库推送到远程库(push) 8.4 远程库拉取到本地库(pull) 8.5 远程库克隆到本地库(clone) 8.1 VSCode登录GitHub账号 Step1&#xff1a;安装“GitHub Pull Requests and Issues”插件 Step2&#xff1a;登录GitHub账号 …

Yolov8不废话!参考手册!

Yolov8使用 yolo taskdetect modetrain modelyolov8n.pt args...classify predict yolov8n-cls.yaml args...segment val yolov8n-seg.yaml args...export yolov8n.pt formatonnx args...使用Ultralytics YOLO进行模型训练 …

pygame入门学习(四)位图的使用

大家好&#xff01;我是码银&#x1f970; 欢迎关注&#x1f970;&#xff1a; CSDN&#xff1a;码银 公众号&#xff1a;码银学编程 载入图片 pygame.image.load( )&#xff0c;Pygame 可以通过pygame.image.load( )函数处理位图文件。 大致可以支持以下文件&#xff1a;JPG…

一.Winform使用Webview2(Edge浏览器核心) 创建demo(Demo1)实现回车导航到指定地址

Winform使用Webview2创建demo1实现回车导航到指定地址 往期目录参考文档实现1.安装visual studio2.创建单窗口应用3.修改项目中的窗体名称MainForm4.添加按钮5.添加窗口Demo16.在Demo1中添加WebView2 SDK7.在Demo1窗体中选择添加textbox和webview28.在MainForm.cs窗体中添加but…

PyTorch 添加 C++ 拓展

参考内容&#xff1a;pytorch添加C拓展简单实战编写及基本功能测试 文章目录 第一步&#xff1a;编写 C 模块test.htest.cpp 第二步&#xff1a;编写 setup.py第三步&#xff1a;安装 C 模块第四步&#xff1a;验证安装第五步&#xff1a;C 模块使用test_cpp1.pytest_cpp2.py 运…

yolov8的目标检测、实例分割、关节点估计的原理解析

1 YOLO时间线 这里简单列下yolo的发展时间线&#xff0c;对每个版本的提出有个时间概念。 2 yolov8 的简介 工程链接&#xff1a;https://github.com/ultralytics/ultralytics 2.1 yolov8的特点 采用了anchor free方式&#xff0c;去除了先验设置可能不佳带来的影响借鉴General…

跑步运动耳机哪个牌子好?2024年国产运动耳机推荐

​无论春夏秋冬&#xff0c;无论室内还是户外&#xff0c;运动都能带给我们无尽的乐趣。而一副好的运动耳机&#xff0c;更能为我们的运动体验增色不少。今天&#xff0c;就让我为大家推荐几款值得一试的运动耳机吧。 1.南卡开放式耳机&#xff08;00压&#xff09; 一句话评价…

VUE项目目录与运行流程(VScode)

各目录对应名称含义 main.js&#xff08;导入App.vue&#xff0c;基于App.vue创建结构渲染index.html&#xff09; //核心作用&#xff1a;导入App.vue&#xff0c;基于App.vue创建结构渲染index.html//1.导入Vue核心包 import Vue from vue//2.导入App.vue根组件 import App f…

如何在 Ubuntu 22.04 上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈

前些天发现了一个人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;最重要的屌图甚多&#xff0c;忍不住分享一下给大家。点击跳转到网站。 如何在 Ubuntu 22.04 上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈 介绍 “LAMP”堆栈是一组开源软件&#…

基于ssm框架的网上购物系统-计算机毕业设计源码12503

摘 要 近年来&#xff0c;随着移动互联网的快速发展&#xff0c;电子商务越来越受到网民们的欢迎&#xff0c;电子商务对国家经济的发展也起着越来越重要的作用。简单的流程、便捷可靠的支付方式、快捷畅通的物流快递、安全的信息保护都使得电子商务越来越赢得网民们的青睐。现…

控制项目进展

优质博文 IT-BLOG-CN 假如一个项目准备工作做的非常周详&#xff0c;现在要做的就是监督项目的进展情况&#xff0c;理想状况下事情应当进展的很顺利&#xff0c;但实际上我们会发现项目永远不会完全按照经计划执行&#xff0c;我们必须进行项目控制。也就是我们需要不断进行调…

创建SERVLET

创建SERVLET 要创建servlet,需要执行以下任务: 编写servlet。编译并封装servlet。将servlet部署为Java EE应用程序。通过浏览器访问servlet。编写servlet 要编写servlet,需要扩展HttpServlet接口的类。编写servlet是,需要合并读取客户机请求和返回响应的功能。 读取和处…