Diesel 的安装与数据库迁移

发布于:2024-05-09 ⋅ 阅读:(33) ⋅ 点赞:(0)

Diesel 所需 Rust 版本 >= 1.65

安装至项目

修改 Cargo.toml

[dependencies]
diesel = { version = "2.1.0", features = ["postgres"] }
dotenvy = "0.15"

安装 CLI

Diesel 提供了用于管理项目的命令行工具,可以通过 cargo 安装。

cargo install diesel_cli

但是,你可能会遇到这样的问题:

note: ld: library not found for -lmysqlclient
clang: error: linker command failed with exit code 1 (use -v to see invocation)

这是系统缺乏相关的用于操作数据库的链接库导致的,这里阐述使用 Sqlite 的时候的解决方法。

  1. 在报错的终端搜索 LIBPATH,复制其值;

  2. 打开 LIBPATH 所在的目录,我们需要把链接库放在这里;

  3. 对于 Sqlite,我们可以在 Cargo.toml 的 [dependencies] 块中加入:

    rusqlite = { version = "0.31.0", features = ["bundled"] }
    
  4. 编译项目,然后在编译目录下的 build 文件夹找到 libsqlite3-sys-* 文件夹,* 表示一串哈希字符串。可能会包含多个这样的文件夹。找到其中包含的 out/libsqlite3.a 文件,把 libsqlite3.a 复制到前面打开的 LIBPATH 中。

  5. 再次安装CLI,由于我们只添加了 sqlite 库,所以我们需要指定 features

    cargo install diesel_cli --no-default-features --features sqlite
    

    对于其它数据库,features 需要如下填写

    数据库 features
    MySQL mysql
    PostgreSQL postgres
    SQLite sqlite

    diesel/.github/workflows/ci.yml at master · diesel-rs/diesel

项目初步设置

首先,我们需要在项目根目录下创建一个 .env 文件,在其中写入数据库的地址:

DATABASE_URL=postgres://username:password@localhost/diesel_demo

对于SQLite 数据库,示例如下:

DATABASE_URL=sqlite://database.db

Windows 下不建议使用 echo 指令,因为操作系统可能不会以 UTF8 格式写入文件,导致文件无法读取

然后,我们就可以使用 CLI 让 Diesel 帮我们初始化项目,包括:

  • 创建数据库
  • 创建数据库迁移文件夹(用于生成数据库结构)

创建第一个表

对于表的创建,Diesel 需要同时拥有过该表的迁移和 Schema,但 Diesel 可以根据其一生成另一。

  • 手动定义 迁移,Diesel 在迁移时自动生成 Schema
  • 手动定义 Schema,Diesel 在迁移时自动生成 迁移

创建第一个表(SQL)

我们可以使用 Diesel 的数据库迁移功能来创建数据库结构,并对数据库的结构进行版本控制。首先,我们需要生成迁移文件:

diesel migration generate create_posts

其中 create_posts 即为迁移的名称,最终会以 时间_crewate_posts 方式生成文件夹,并生成 up.sqldown.sql 分别用于构建和撤销数据库结构。

举例来说,我们可以在 up.sql 中写入:

CREATE TABLE posts (
  id SERIAL PRIMARY KEY,
  title VARCHAR NOT NULL,
  body TEXT NOT NULL,
  published BOOLEAN NOT NULL DEFAULT FALSE
)	

down.sql 中删除改表:

DROP TABLE posts

创建迁移后,我们可以开始迁移(根据 up.sql

diesel migration run

也可以撤销已经进行的迁移(根据 down.sql

diesel migration redo

创建第一个表 (schema)

使用 SQL 创建迁移可以最大程度地保留灵活性,但是 Diesel 也支持使用 schema 来进行迁移,我们将在 schema 文件中定义表及其对应的 Rust 类型,Diesel 会自动推断其在数据库中的类型。

创建 schema.rs 文件,并写入表结构,如:

diesel::table! {
    posts (id) {
        id -> Int4,
        title -> Varchar,
        body -> Text,
        published -> Bool,
    }
}

然后,我们还需要生成迁移文件:

diesel migration generate --diff-schema create_posts

有了迁移文件后,一切就如前文所述的一样运行迁移即可。

生产环境下运行迁移

我们不能要求用户安装 Diesel CLI 并运行迁移指令,Diesel 提供了在代码中运行迁移的方法,这个方法是:

  1. 使用在 diesel_migrations crate 中的 embed_migrations! 宏,这样迁移文件会包含在最终的二进制文件中;
  2. 使用 connection.run_pending_migrations(MIGRATIONS) 代码进行迁移。

示例

diesel_migrations = { version = "2.1.0", features = ["sqlite"]}
use diesel::sqlite::SqliteConnection;
use diesel::prelude::*;
use dotenvy::dotenv;
use std::env;
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};

pub fn establish_connection() -> SqliteConnection {
    dotenv().ok();
    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    SqliteConnection::establish(&database_url)
        .unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
}

fn main() {
    let conn = &mut establish_connection();
    const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
    let _ = conn.run_pending_migrations(MIGRATIONS);

	// ...
}

embed_migrations in diesel_migrations - Rust (docs.rs)

注意,若不引入 diesel_migrations::MigrationHarness trait,则无法使用 run_pending_migrations 方法。