はじめに
今回は、Rustの人気ORMパッケージであるSeaORMをインストールから、簡単なデータベース操作までを解説します。

なお、今回紹介するソースコードはこちらにあります。
また、RustのデスクトップアプリライブラリであるTauriで簡単なTodoアプリ作成を記事にしています。
【Tauri入門】Next.js × Tauriで軽量デスクトップアプリ開発を始めよう – Todoアプリを作る①

インストール方法
こちらを元にインストールを行なっていきます。

Cargo.tomlにパッケージを追加する
まずは、Cargo.tomlの[dependencies]の下に、こちらを追加します。
sea-orm = { version = "1.1.0", features = [ "sqlx-sqlite", "runtime-async-std-native-tls", "macros" ] }
今回は、SQLiteを使用するため、featuresに”sqlx-sqlite”を設定しています。
その他、使用するDBのドライバーに沿ったものを記載します。
| 設定値 | 使用するDB | 
| Msqlx-mysql | MySQL と MariaDB | 
| sqlx-postgres | PostgreSQL | 
| sqlx-sqlite | SQLite | 
また、”runtime-async-std-native-tls”には他に設定する値として、設定する項目はこの2つを選んで設定します。
- 非同期ランタイム(ASYNC_RUNTIME)
→ Rustの非同期処理を支える仕組み - TLSライブラリ(TLS_LIB)
→ HTTPSなどの安全な通信を行うための仕組み 
これらを組み合わせた形式(runtime-ASYNC_RUNTIME-TLS_LIB)で設定します。
なお、設定については下記の4点が設定できます。
| 設定値 | 説明 | 
| runtime-async-std-native-tls | `async-std`ランタイム + OS依存のTLS | 
| runtime-tokio-native-tls | `tokio`ランタイム + OS依存のTLS | 
| runtime-async-std-rustls | `async-std`ランタイム + Rust実装のTLS | 
| runtime-tokio-rustls | `tokio`ランタイム + Rust実装のTLS | 
データベースのエンティティを作成する
新しく、データベースを作成します。
まずは、sea-orm-cliをインストールします。
cargo install sea-orm-cli@1.1.0
次に、初期化処理を行います。
sea-orm-cli migrate init
このコマンドを実行すると、migrationディレクトリが作成され、バージョンアップなどでテーブルが増えたり、カラムが変更されたりしても、マイグレーションを行うことができます。
migration/srcディレクトリ配下にm20220101_000001_create_table.rsのファイルが作成されて今。
このファイルでは、テーブルの定義ファイルでサンプルとしてPostテーブルを作成しており、カラムについても定義されています。
migration/Cargo.tomlに使用するドライバなどを記載する
次に、インストール時に追加した、使用するドライバとランタイムの設定を追加します。
[dependencies.sea-orm-migration]
version = "1.1.0"
features = [
  "sqlx-sqlite", "runtime-tokio-rustls",
]
実際にデータベースを作成
今回は、sqliteを使っていますので、データベースファイルを作成します。
まずは、rustプロジェクトのルートディレクトリに.envファイルを作成し、DATABASE_URLを記載します。
DATABASE_URL="sqlite://db.sqlite?mode=rwc"
次は、migrateコマンドで実際にデータベースを作成しましょう。
sea-orm-cli migrate refresh
このコマンドを実行するとプロジェクトルート/db.sqliteが作成されます。
エンティティファイル作成
最後に、プロジェクトで使うためにエンティティファイルを作成します。
sea-orm-cli generate entity -o src/entities
なお、-oのオプションは、エンティティファイルを作成するディレクトリを指定します。
作成された、post.rsが実際にmigrationで定義したテーブル定義のエンティティファイルが作成されています。
データベースの読み書きを行う
これで、データベースを扱う準備が整いました。
では、実際にデータベースの読み書きを行なっていきます。
データベースに接続する
まず、データベースに接続します。
let db: DatabaseConnection = Database::connect("sqlite://db.sqlite?mode=rwc").await?;
その他のデータベースでは下記のようになります。
MySQL
let db: DatabaseConnection = Database::connect("mysql://username:password@host/database").await?;
PostgreSQL
let db: DatabaseConnection = Database::connect("postgres://username:password@host/database?currentSchema=my_schema").await?;
SQLite
メモリに保存する
let db: DatabaseConnection = Database::connect("sqlite::memory:").await?;
読み取り専用のデータベースとして使用する
let db: DatabaseConnection = Database::connect("sqlite://path/to/db.sqlite?mode=ro").await?;
読み書きしてみる
今回は、非同期処理があるので、cargo.tomlにasync-std = { version = "1.12", features = ["attributes"] }を追加して非同期処理ができるようにしました。
use sea_orm::{Database, DatabaseConnection, EntityTrait};
pub mod entities;
fn main() {
    async_std::task::block_on(async {
        if let Err(e) = db_connection().await {
            eprintln!("DB error: {:?}", e);
        }
    });
}
async fn db_connection() -> Result<(), sea_orm::DbErr> {
    let db: DatabaseConnection = Database::connect("sqlite://db.sqlite?mode=rwc").await?;
    // 新しい投稿データを作成(titleとtextをセット、他のフィールドはデフォルト値)
    let data = entities::post::ActiveModel {
    title: sea_orm::ActiveValue::Set("Sample Title".to_owned()),
    text: sea_orm::ActiveValue::Set("Sample text content".to_owned()),
      ..Default::default()
    };
    // データベースに投稿を挿入
    entities::post::Entity::insert(data).exec(&db).await?;
    // 投稿テーブルから1件だけ取得
    let cheese: Option = entities::post::Entity::find().one(&db).await?;
    if let Some(post) = cheese {
        println!("Post found: {:?}", post);
    } else {
        println!("No post found.");
    }
    Ok(())
}
      
  
  
  
  