跳到主要内容
版本:2.0.x

展开的 Entity 格式

这是 Compact 格式之前的实体格式,如今 Compact 格式已成为默认,所有新功能都建立在 Compact 格式之上。

展开格式被视为遗留格式。如果你好奇 DeriveEntityModel 会展开成什么,请继续阅读。

展开的实体格式可通过 sea-orm-cli 使用 --entity-format=expanded 选项生成。

让我们浏览展开后的 Cake 实体的各个部分。

实体

通过实现 EntityTrait,你可以对给定表执行 CRUD 操作。

#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
pub struct Entity;

impl EntityName for Entity {
fn schema_name(&self) -> Option<&str> {
None
}

fn table_name(&self) -> &str {
"cake"
}
}

表示此表中所有列的枚举。

#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
pub enum Column {
Id,
Name,
}

impl ColumnTrait for Column {
type EntityName = Entity;

fn def(&self) -> ColumnDef {
match self {
Self::Id => ColumnType::Integer.def(),
Self::Name => ColumnType::String(StringLen::None).def(),
}
}
}

所有列名默认采用 snake-case。你可以通过指定 column_name 属性覆盖列名。

pub enum Column {
Id, // maps to "id" in SQL
Name, // maps to "name" in SQL
#[sea_orm(column_name = "created_at")]
CreatedAt // maps to "created_at" in SQL
}

要指定每列的数据类型,可使用 ColumnType 枚举。

附加属性

  • 默认值
  • 唯一
  • 索引
  • 可空
ColumnType::String(StringLen::None).def().default_value("Sam").unique().indexed().nullable()

Select 和 Save 时的列类型转换

如果你需要以某种类型查询列,但以另一种类型保存到数据库,可以覆盖 select_assave_as 方法进行类型转换。典型用例是将 citext(不区分大小写的文本)类型的列在 Rust 中作为 String 查询,保存到数据库时作为 citext。应按如下方式覆盖 ColumnTrait 的方法:

use sea_orm::sea_query::{Expr, SimpleExpr, Alias}

impl ColumnTrait for Column {
// Snipped...

/// Cast column expression used in select statement.
fn select_as(&self, expr: Expr) -> SimpleExpr {
match self {
Column::CaseInsensitiveText => expr.cast_as("text"),
_ => self.select_enum_as(expr),
}
}

/// Cast value of a column into the correct type for database storage.
fn save_as(&self, val: Expr) -> SimpleExpr {
match self {
Column::CaseInsensitiveText => val.cast_as("citext"),
_ => self.save_enum_as(val),
}
}
}

主键

表示此表主键的枚举。复合主键由具有多个变体的枚举表示。

ValueType 定义 InsertResult 中 last_insert_id 的类型。

auto_increment 定义主键是否具有自动生成的值。

#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
pub enum PrimaryKey {
#[sea_orm(column_name = "id")] // Override the default column name
Id, // maps to "id" in SQL
}

impl PrimaryKeyTrait for PrimaryKey {
type ValueType = i32;

fn auto_increment() -> bool {
true
}
}

复合主键示例

pub enum PrimaryKey {
CakeId,
FruitId,
}

impl PrimaryKeyTrait for PrimaryKey {
type ValueType = (i32, i32);

fn auto_increment() -> bool {
false
}
}

模型

用于存储查询结果的 Rust 结构体。

#[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
pub struct Model {
pub id: i32,
pub name: String,
}

可空属性

若表列可为空,请用 Option 包装。

pub struct Model {
pub id: i32,
pub name: Option<String>,
}

ActiveModel

ActiveModel 拥有其对应 Model 的所有属性,但所有属性都包装在 ActiveValue 中。

#[derive(Clone, Debug, PartialEq)]
pub struct ActiveModel {
pub id: ActiveValue<i32>,
pub name: ActiveValue<Option<String>>,
}

关联

指定与其他实体的关系。

#[derive(Copy, Clone, Debug, EnumIter)]
pub enum Relation {
Fruit,
}

impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::Fruit => Entity::has_many(super::fruit::Entity).into(),
}
}
}

关联实体

定义特征约束以帮助你一起查询关联实体,在多对多关系中尤其有用。

impl Related<super::fruit::Entity> for Entity {
fn to() -> RelationDef {
Relation::Fruit.def()
}
}

impl Related<super::filling::Entity> for Entity {
fn to() -> RelationDef {
super::cake_filling::Relation::Filling.def()
}

fn via() -> Option<RelationDef> {
Some(super::cake_filling::Relation::Cake.def().rev())
}
}