sea-orm-2
SeaORM 2.0に関する専門的なガイダンスを提供します。SeaORMはRustの非同期ORM(オブジェクト・リレーショナル・マッピング)であり、強く型付けされたカラム、ネストされたActiveModel、Entity Loader API、エンティティファーストなワークフローの特徴があります。SeaORMを使用したRustプロジェクトでエンティティ、クエリ、マイグレーション、リレーション、またはそのほかのデータベース操作に関わる際に活用できます。新しい2.0のAPIパターン、回避すべきアンチパターン、および1.0からのマイグレーション方法に対応しています。
description の原文を見る
Expert guidance for SeaORM 2.0, Rust's async ORM with strongly-typed columns, nested ActiveModels, Entity Loader API, and entity-first workflow. Use when working with SeaORM entities, queries, migrations, relations, or any database operations in Rust projects using SeaORM. Covers the new 2.0 API patterns, anti-patterns to avoid, and migration from 1.0.
SKILL.md 本文
SeaORM 2.0
このスキルは、SeaORM 2.0を適切に使用するためのエキスパートガイダンスを提供します。新しいパターンに焦点を当て、SeaORM 1.0の知識から生じる一般的な落とし穴を避けることを目指しています。
クイックリファレンス
エンティティ定義 (2.0 フォーマット)
SeaORM 2.0は #[sea_orm::model] を使用し、リレーションは Model 構造体に直接定義されます。これにより、1.0パターンの独立した Relation 列挙型と Related トレイト実装が置き換わります。
基本的なエンティティ
mod user {
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "user")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(unique)]
pub email: String,
}
impl ActiveModelBehavior for ActiveModel {}
}
リレーション付きエンティティ
mod user {
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "user")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(unique)]
pub email: String,
#[sea_orm(has_one)]
pub profile: HasOne<super::profile::Entity>,
#[sea_orm(has_many)]
pub posts: HasMany<super::post::Entity>,
}
}
リレーション型
// Has-One
#[sea_orm(has_one)]
pub profile: HasOne<super::profile::Entity>,
// Has-Many
#[sea_orm(has_many)]
pub posts: HasMany<super::post::Entity>,
// Belongs-To (外部キーマッピング明示)
#[sea_orm(belongs_to, from = "user_id", to = "id")]
pub user: HasOne<super::user::Entity>,
// Many-to-Many (ジャンクションテーブル経由)
#[sea_orm(has_many, via = "post_tag")]
pub tags: HasMany<super::tag::Entity>,
// 自己参照
#[sea_orm(self_ref, via = "user_follower", from = "User", to = "Follower")]
pub followers: HasMany<Entity>,
ジャンクションテーブル (複合主キー)
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "post_tag")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub post_id: i32,
#[sea_orm(primary_key, auto_increment = false)]
pub tag_id: i32,
#[sea_orm(belongs_to, from = "post_id", to = "id")]
pub post: Option<super::post::Entity>,
#[sea_orm(belongs_to, from = "tag_id", to = "id")]
pub tag: Option<super::tag::Entity>,
}
詳細なエンティティパターンは references/entity-patterns.md を参照してください。
強く型付けされたカラム (2.0)
型付けされていない Column 列挙型の代わりに、COLUMN 定数と型付きフィールドを使用します:
// 2.0 (推奨) -- コンパイル時型安全性
user::Entity::find().filter(user::COLUMN.name.contains("Bob"))
// 1.0 (廃止) -- 動作しますが COLUMN を使用することを推奨
user::Entity::find().filter(user::Column::Name.contains("Bob"))
COLUMN 定数は以下を提供します:
- コンパイル時の型チェック
- より優れたIDE自動補完
- リファクタリング安全性
ActiveModel ビルダーパターン (2.0)
ネストされたリレーションを含む作成
// ネストされたリレーション付きで作成
let bob = user::ActiveModel::builder()
.set_name("Bob")
.set_email("bob@sea-ql.org")
.set_profile(profile::ActiveModel::builder().set_picture("Tennis"))
.insert(db)
.await?;
Has-Many 子を追加
let mut bob = bob.into_active_model();
bob.posts.push(
post::ActiveModel::builder().set_title("My first post")
);
bob.save(db).await?;
Many-to-Many リレーション
let post = post::ActiveModel::builder()
.set_title("A sunny day")
.set_user_id(bob.id)
.add_tag(existing_tag)
.add_tag(tag::ActiveModel::builder().set_tag("outdoor"))
.save(db)
.await?;
完全な ActiveModel パターンは references/activemodel-patterns.md を参照してください。
Entity Loader API (2.0)
Entity Loader は、1-1 リレーションで JOIN を、1-N リレーションでデータローダーを利用して、N+1 クエリを排除します。
基本的な読み込み
// 単一クエリでリレーション付きで読み込み
let bob = user::Entity::load()
.filter_by_email("bob@sea-ql.org")
.with(profile::Entity)
.with(post::Entity)
.one(db)
.await?
.expect("Not found");
ネストされたリレーション
// ネストされたリレーション (post -> comments)
let user = user::Entity::load()
.filter_by_id(12)
.with(profile::Entity)
.with((post::Entity, comment::Entity))
.one(db)
.await?;
動作原理
// join パス:
// user -> profile
// user -> post
// post -> post_tag -> tag
let smart_user = user::Entity::load()
.filter_by_id(42)
.with(profile::Entity) // 1-1 は join を使用
.with((post::Entity, tag::Entity)) // 1-N はデータローダーを使用
.one(db)
.await?
.unwrap();
// 内部で3つのクエリが実行されます:
// 1. SELECT FROM user JOIN profile WHERE id = $
// 2. SELECT FROM post WHERE user_id IN (..)
// 3. SELECT FROM tag JOIN post_tag WHERE post_id IN (..)
高度なクエリパターンは references/query-patterns.md を参照してください。
スキーマレジストリ (エンティティ優先ワークフロー)
SeaORM 2.0 はエンティティを定義して SeaORM がスキーマを作成するエンティティ優先開発をサポートしています。
// エンティティ定義からテーブルを自動作成 (開発/テスト)
db.get_schema_registry("my_crate::*")
.sync(db)
.await?;
以下を実行します:
- 外部キーの依存関係に基づいてトポロジカルオーダーでテーブルを作成
- 既存テーブルに新しいカラムを追加
- ユニークキーと外部キーを自動作成
機能フラグが必要: entity-registry と schema-sync。
避けるべきアンチパターン
1. カスタム ラッパー型に column_type を指定しない
// 間違い -- カスタム型に column_type を注釈しない
#[sea_orm(column_type = "Decimal(Some((10, 4)))")]
pub speed: Speed,
// 正しい -- SeaORM は DeriveValueType からカラム型を推論
pub speed: Speed,
#[derive(Clone, Debug, PartialEq, DeriveValueType)]
pub struct Speed(Decimal);
2. MySQL/MSSQL では長い文字列に Text を使用
// MySQL/MSSQL で間違い -- 255文字で無言のうちに切り捨てられる
pub description: String,
// 正しい -- より長い文字列には column_type を使用
#[sea_orm(column_type = "Text")]
pub description: String,
// また正しい -- 明示的な最大長
#[sea_orm(column_type = "String(StringLen::Max)")]
pub event_type: String,
3. ExprTrait インポートの漏れ
2.0 では Expr の .eq()、.like()、.contains() などのメソッドに トレイトインポートが必要です:
use sea_orm::ExprTrait; // 2.0 では必須
Expr::col((self.entity_name(), *self)).like(s)
4. 削除または名前が変更された API を使用しない
| 1.0 (削除/名前変更) | 2.0 (正しい) |
|---|---|
.into_condition() | .into() |
db.execute(Statement::from_sql_and_values(..)) | db.execute_raw(Statement::from_sql_and_values(..)) |
db.query_all(backend.build(&query)) | db.query_all(&query) |
Alias::new("col") 静的文字列用 | Expr::col("col") 直接使用 |
insert_many(..).on_empty_do_nothing() | insert_many([]) は安全に None を返す |
5. DeriveValueType が生成するトレイトを手動で実装しない
2.0 では DeriveValueType は自動的に NotU8、IntoActiveValue、TryFromU64 を生成します。競合を避けるため、手動実装を削除してください。
6. PostgreSQL: serial は不変のデフォルトではなくなった
自動増分カラムは現在 GENERATED BY DEFAULT AS IDENTITY を使用します。レガシーな動作には機能フラグ postgres-use-serial-pk を使用してください。
7. SQLite: 整数型マッピングが変更
2.0 では Integer と BigInteger の両方が integer にマップされます。必要に応じて sea-orm-cli --big-integer-type=i32 を使用してください。
完全なマイグレーションガイドは references/migration-guide.md を参照してください。
一般的な操作クイックリファレンス
Select
// すべて検索
let cakes: Vec<cake::Model> = Cake::find().all(db).await?;
// フィルター
let chocolate: Vec<cake::Model> = Cake::find()
.filter(Cake::COLUMN.name.contains("chocolate"))
.all(db)
.await?;
// ID で検索
let cheese: Option<cake::Model> = Cake::find_by_id(1).one(db).await?;
// 関連を前読み込み (1-1)
let cake_with_fruit: Vec<(cake::Model, Option<fruit::Model>)> =
Cake::find().find_also_related(Fruit).all(db).await?;
// 関連を前読み込み (1-N および M-N)
let cake_with_fillings: Vec<(cake::Model, Vec<filling::Model>)> = Cake::find()
.find_with_related(Filling)
.all(db)
.await?;
Insert
let apple = fruit::ActiveModel {
name: Set("Apple".to_owned()),
..Default::default()
};
// 1 つ挿入
let apple = apple.insert(db).await?;
// 複数挿入
let result = Fruit::insert_many([apple, pear]).exec(db).await?;
Update
let pear: Option<fruit::Model> = Fruit::find_by_id(1).one(db).await?;
let mut pear: fruit::ActiveModel = pear.unwrap().into();
pear.name = Set("Sweet pear".to_owned());
let pear: fruit::Model = pear.update(db).await?;
// 一括更新
Fruit::update_many()
.col_expr(fruit::COLUMN.cake_id, fruit::COLUMN.cake_id.add(2))
.filter(fruit::COLUMN.name.contains("Apple"))
.exec(db)
.await?;
Delete
// 1 つ削除
orange.delete(db).await?;
// 複数削除
fruit::Entity::delete_many()
.filter(fruit::COLUMN.name.contains("Orange"))
.exec(db)
.await?;
機能フラグ
知っておくべき主要な機能フラグ:
sqlx-mysql,sqlx-postgres,sqlx-sqlite- データベースドライバruntime-tokio-native-tls,runtime-tokio-rustls- 非同期ランタイムwith-chrono,with-time- 日付/時刻ライブラリwith-rust_decimal,with-bigdecimal- 十進数ライブラリwith-json- JSON サポートentity-registry,schema-sync- エンティティ優先ワークフローpostgres-use-serial-pk- レガシー PostgreSQL serial 型
references/entity-patterns.md
- 基本的なエンティティ構造
- すべてのリレーション型 (Has-One、Has-Many、Many-to-Many、Self-referential)
- 複合主キー
- DeriveValueType を使用したカスタム型
- カラム属性リファレンス
references/activemodel-patterns.md
- ActiveModel の作成 (3 つの方法)
- ビルダーパターンの使用
- ネストされた永続化の例
- 更新パターン
- Insert と Save のセマンティクス
- ActiveValue の状態
references/query-patterns.md
- 基本的な CRUD クエリ
- 強く型付けされたカラムでのフィルター
- Entity Loader API パターン
- Join 操作
- ページネーション
- 集計
- パラメータバインディングを伴う生 SQL
references/migration-guide.md
- 完全な 1.0 から 2.0 へのマイグレーションガイド
- 破壊的変更テーブル
- API 名前変更リファレンス
- ステップバイステップのマイグレーション手順
このスキルは SeaORM 2.0 の包括的なカバレッジを提供し、新しいパターンと避けるべき重要なアンチパターンに焦点を当てています。
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- FlyinPancake
- リポジトリ
- FlyinPancake/yoink
- ライセンス
- Apache-2.0
- 最終更新
- 2026/5/10
Source: https://github.com/FlyinPancake/yoink / ライセンス: Apache-2.0