23. rust数据库使用:sea-orm详解

一、前言

只要开发稍微大型一点的项目,数据库都是离不开的。

rust目前并没有特别成熟的数据库框架,sea-orm这个框架是我目前所看到的成熟度最高的一个,并且仍在积极开发中。

所以本文将以sea-orm框架为基础来了解rust中数据库的基本使用。

二、项目管理

sea-orm管理数据库是通过迁移文件完成的,所以想要正常使用sea-orm框架,我们必须得对整个项目进行规划,使用方法便是工作空间。

首先下载sea-orm的命令行工具:

cargo install sea-orm-cli

这个命令行工具可以帮助我们迁移数据库、以及生成表实例等等。

然后在该工作空间内,分别执行命令:

sea-orm-cli migrate init
cargo new entity --lib
cargo new app

这三个命令用于在本工作空间内创建项目,也就是crate,其中前两个最好不要动,至于第三个命令,你可以随意修改它的名字,它是你实际写代码业务逻辑的地方。

此时我们整个工作空间看起来大致像下面这样:

image.png

注意使用sea-orm-cli生成的crate,它的名字需要我们手动添加到工作空间成员中去,至于其它两个,会自动添加。

至此我们就完成了整个项目的搭建,各个crate的作用如下:

  • migration:用于管理迁移文件的crate,说白了就是这个crate可以让我们通过代码创建数据库的表,只要迁移文件在,即使你数据库被删了,也能快速恢复过来(仅限表结构,不含数据)。
  • entity:用于包含所有表所对应的实体结构,你可以将其看作是数据库到代码的一个映射关系,以后你任何想要对数据库的表的增删改查操作,都要通过这个crate进行,并且这个crate中的代码后续是通过sea-orm-cli工具自动根据数据库生成的,你无需自行维护。
  • app:你实际的项目业务逻辑代码,当你想要操作数据库中的表时,引入entity这个crate即可。

三、迁移文件

为了方便起见,这里使用sqlite3数据库作为演示,它无需我们去安装其它任何东西。

但无论如何,迁移文件本身是数据库无关的,所以我们先来看迁移crate为我们自动生成的代码:

image.png

首先移除掉todo!()宏,去除警告,上面的这个迁移文件是自动为我们生成的。

首先看到这个文件的名字:m20220101_000001_create_table,其中首字母m是migration的缩写,后面跟着的数字是年月日、时分秒,最后的create_table则是这个迁移文件的含义,也就是创建表的意思。

注意,这里的迁移文件后面我们是通过命令自动生成的,所以文件名格式、包括这个文件中的代码样式,都不用我们操心。

我们在自动生成的迁移文件代码中,只需要关注三个地方:

  1. up函数,也就是向上的意思,意味项目向前进展过程中所需要对数据库做出的修改。
  2. down函数,也就是向下,意味回退的意思
  3. Post枚举,代表这个迁移文件中所要操作的数据库表

虽然上面自动生成的代码看起来比较繁琐复杂,但实际并不难,首先我们来看标号3的表结构:

#[derive(DeriveIden)]
enum Post {
    Table,
    Id,
    Title,
    Text,
}

这里的Post代表着表的名字,而其内的Table字段则被用来在后续的代码中使用、指代这个本表。

因此实际上,这里的含义就是Post表中有三个字段,分别命名为Id、Title、Text。

其上的#[derive(DeriveIden)]就不用我们管了,它是sea库本身写的过程宏,可以根据这个枚举生成一些代码,方便我们使用,是必须要写上的。

然后我们再来看up函数:

manager.create_table().await

虽然上面有一大串,但实际上就是一个函数,通过传入的manager实例调用其上的create_table函数,用于创建一个表。

这个要创建的表就是我们将要传入的参数,这个参数是通过固定Table模块内函数创建的。

比如这里是创建表,所以就要使用Table中的create函数:

Table::create()
	.table(Post::Table)
	.if_not_exists()

这里就是一系列的链式调用,你不需要管其它的,看这个函数名字你就知道它是在干嘛了。

table函数用来指定你想要创建的表结构,这里指定的就是本文件中的Post表,传入Post::Table即可。

if_not_exists见名知意,就是只要不存在这张表的时候才执行创建。

再之后,就是设置这张表中的每个字段的属性:

.col(
	ColumnDef::new(Post::Id)
		.integer()
		.not_null()
		.auto_increment()
		.primary_key(),
)
.col(ColumnDef::new(Post::Title).string().not_null())
.col(ColumnDef::new(Post::Text).string().not_null())

每个字段都是一列,所以调用col函数,然后根据表字段进行构建ColumnDef::new(Post::Id),每个字段都有四个属性:

  • 类型:比如这里调用integer函数代表Id字段是数字,后面的string函数代表Title、Text字段是字符串
  • 是否可以为空,也就是null,默认允许,你可以调用not_null函数设置不允许
  • 是否自动自增,一般id字段需要自增,所以这里调用auto_increment函数
  • 是否为主键,id字段一般为主键,所以这里调用primary_key函数将其设置为主键。

完成了一张表的代码定义之后,最后调用to_owned函数,获取这个实例的所有权,传入create_table函数,即完成了创建表的代码定义。

作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux