R2DBC-响应式数据库

这篇具有很好参考价值的文章主要介绍了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>

单元测试

    @Test
   public 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.获取到连接,发送sql
       Mono.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();
   }

参数赋值
R2DBC-响应式数据库,数据库

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:3306
    username: root
    password: your_password
    name: 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操作不好做

    @Autowired
    private R2dbcEntityTemplate template;

    @Test
    public 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操作好做

    @Autowired
    private DatabaseClient databaseClient;
    
    @Test
    public 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);
}

测试复杂查询

    @Test
    public 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 {

    @Id
    private 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);
}

绑定查询参数:
R2DBC-响应式数据库,数据库
自定义结果转换器

@ReadingConverter//读取数据库数据时,把row->book
public class BookConverter implements Converter<Row, Book> {
    @Override
    public 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
    @ConditionalOnMissingBean
    public R2dbcCustomConversions conversions () {
        return R2dbcCustomConversions.of(MySqlDialect.INSTANCE,new BookConverter());
    }

}

测试

    @Test
    public 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> {
    @Override
    public 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> {
    @Override
    public 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;

测试文章来源地址https://www.toymoban.com/news/detail-811197.html

    @Test
    public 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();
    }

到了这里,关于R2DBC-响应式数据库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据库原理】(32)数据库设计-数据库物理设计

    数据库的物理设计是数据库设计过程中至关重要的一个阶段。其核心目标是选择一个适合应用环境的物理结构,以满足特定的性能、存储和访问需求。这一阶段涉及的关键任务可以分为两个主要步骤: 1. 确定数据的物理结构 存储结构和存取方法的选择 :这包括决定数据在物

    2024年01月19日
    浏览(42)
  • 【数据库概论】图数据库 Vs 关系数据库(1)

    假设有一个社交网络需要用数据库存储,其中人与人之间的关系有:朋友(friend)、父母(parent) 首先用关系数据库来实现朋友关系,需要 3 张表:people、people_relation、relation 如果要查询 Jam 的所有朋友的信息,那么就需要连接三张表: 如果表的数据量较大,那么查询效率就

    2024年03月14日
    浏览(34)
  • 【数据库】 | 初始数据库

    🎗️ 博客新人,希望大家一起加油进步 🎗️ 乾坤未定,你我皆黑马 1、什么是数据库 存储数据用文件就可以了,为什么还要弄个数据库? 文件保存数据有以下几个缺点: 文件的安全性问题 文件不利于数据查询和管理 文件不利于存储海量数据 文件在程序中控制不方便 数据

    2023年04月23日
    浏览(45)
  • 【数据库】数据库设计

    数据库设计面对的主要有哪些问题 (1) 懂数据库原理同时懂甲方软件专业知识的人缺少; (2) 应用的数据库系统的最终目标往往在一开始不能完全明确,与开发者与用户方最初没在要求完全一致有关; (3) 应用业务系统千差万别的,难以找到一种通用的工具和方法。 (1) 对人员

    2024年02月05日
    浏览(45)
  • 数据库应用:数据库管理系统与安装MySQL数据库

    目录 一、理论 1.数据库管理系统 2.关系型数据库 3.数据库 4.MySQL数据库 5.MySQL部署 二、实验 1.yum安装MySQL 2.编译安装MySQL 3.配置MySQL数据库的Tab补全  三、问题 1.数据库登录报错 2.数据库密码复杂度报错 3.数据库连接报错 四、总结 (1)概念 数据库管理系统(Database Management

    2024年02月13日
    浏览(44)
  • MySQL数据库:数据库管理系统与安装MySQL数据库

    目录 一、理论 1.数据库管理系统 2.关系型数据库 3.数据库 4.MySQL数据库 5.MySQL部署 二、实验 1.yum安装MySQL 2.编译安装MySQL 3.配置MySQL数据库的Tab补全  三、问题 1.数据库登录报错 2.数据库密码复杂度报错 3.数据库连接报错 四、总结 (1)概念 数据库管理系统(Database Management

    2024年02月12日
    浏览(46)
  • 数据库优化(数据库自身的优化,数据库表优化,程序操作优化)

    1. 增加次数据文件 从SQL SERVER 2005开始,数据库不默认生成NDF数据文件,一般情况下有一个主数据文件(MDF)就够了,但是有些大型的数据库,由于信息很多,而且查询频繁,所以为了提高查询速度,可以把一些表或者一些表中的部分记录分开存储在不同的数据文件里 由于C

    2024年02月14日
    浏览(32)
  • 【数据库】数据库常用函数

    TIMESTAMPDIFF 是一个MySQL函数,用于计算两个日期或时间之间的差值。函数返回两个日期或时间之间的差值,并以指定的单位表示。 语法: 其中: unit 是计算的单位。可以是以下值:YEAR(年)、QUARTER(季度)、MONTH(月)、DAY(天)、HOUR(小时)、MINUTE(分钟)、SECOND(秒)

    2024年02月11日
    浏览(28)
  • Android studio 连接SQLite数据库 +创建数据库+创建数据库表

    Android studio 之数据库的使用 连接创建SQLite 大家好,欢迎来到寒依。 相信看啦我的教程 当老师问你在学习Android studio 数据库使用过程中遇到什么困难,分享一下你的感悟和解决方法 的时候,你可以直接大胆的说出来: “老师我没有遇到问题,看啦寒依的教程 畅行无阻” 我

    2024年02月02日
    浏览(45)
  • 什么是向量数据库?向量数据库工作原理?向量数据库解决方案?

    向量数据库是一种专门用于存储和处理向量数据的数据库系统。向量数据是指具有多维度属性的数据,例如图片、音频、视频、自然语言文本等。传统的关系型数据库通常不擅长处理向量数据,因为它们需要将数据映射成结构化的表格形式,而向量数据的维度较高、结构复杂

    2024年02月15日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包