Skip to content

Navigation Menu

Sign in
Sign up
RAprogramm edited this page Jul 4, 2026 · 20 revisions

entity-derive 支持的所有属性完整指南。

实体级属性

通过 #[entity(...)] 应用于结构体:

#[derive(Entity)]
#[entity(
 table = "users",
 schema = "core",
 sql = "full",
 dialect = "postgres",
 uuid = "v7",
 soft_delete,
 returning = "full",
 error = "AppError",
 events,
 hooks,
 commands
)]
pub struct User { /* ... */ }

快速参考

属性 必需 默认值 描述
table 数据库表名
schema "public" 数据库模式
sql "full" SQL生成级别
dialect "postgres" 数据库方言
uuid "v7" ID生成的UUID版本
soft_delete false 启用软删除
returning "full" RETURNING子句模式
upsert(...) 生成基于 INSERT ... ON CONFLICT 的 upsert 方法
error sqlx::Error 自定义错误类型
events false 生成生命周期事件
hooks false 生成生命周期钩子trait
commands false 启用CQRS命令模式

table(必需)

数据库表名。

#[entity(table = "users")] // → FROM users
#[entity(table = "user_profiles")] // → FROM user_profiles

schema(可选)

数据库模式。默认:"public"

#[entity(table = "users")] // → FROM public.users
#[entity(table = "users", schema = "core")] // → FROM core.users
#[entity(table = "users", schema = "auth")] // → FROM auth.users

sql(可选)

SQL生成级别。默认:"full"

Repository Trait PgPool实现 用例
"full" 标准CRUD实体
"trait" 自定义查询(joins、CTEs)
"none" 仅DTO,无数据库
#[entity(table = "users", sql = "full")] // 完全自动化(默认)
#[entity(table = "users", sql = "trait")] // 仅trait,自己实现SQL
#[entity(table = "users", sql = "none")] // 完全无数据库层

dialect(可选)

SQL生成的数据库方言。默认:"postgres"

方言 别名 客户端类型 状态
"postgres" "pg", "postgresql" sqlx::PgPool 稳定
"clickhouse" "ch" clickhouse::Client 计划中
"mongodb" "mongo" mongodb::Client 计划中

uuid(可选)

自动生成主键的UUID版本。默认:"v7"

版本 方法 属性
"v7" Uuid::now_v7() 时间排序,可排序(推荐)
"v4" Uuid::new_v4() 随机,广泛兼容
#[entity(table = "users", uuid = "v7")] // 时间排序(默认)
#[entity(table = "sessions", uuid = "v4")] // 随机UUID

为什么选择UUID v7?

  • 时间排序:按创建时间自然排序
  • 更好的数据库索引性能
  • 无需协调(不像序列)
  • 在分布式系统中全局唯一

soft_delete(可选)

启用软删除,将记录标记为已删除而不是移除它们。

#[derive(Entity)]
#[entity(table = "documents", soft_delete)]
pub struct Document {
 #[id]
 pub id: Uuid,
 #[field(create, response)]
 pub title: String,
 #[field(skip)]
 pub deleted_at: Option<DateTime<Utc>>, // 必需字段
}

生成的方法:

  • delete() — 设置 deleted_at = NOW() 而不是 DELETE
  • hard_delete() — 永久删除记录
  • restore() — 设置 deleted_at = NULL
  • find_by_id() / list() — 自动过滤已删除的记录
  • find_by_id_with_deleted() / list_with_deleted() — 包含已删除的记录

returning(可选)

控制INSERT/UPDATE后获取什么数据。默认:"full"

模式 SQL子句 用例
"full" RETURNING * 获取所有字段包括DB生成的(默认)
"id" RETURNING id 确认插入,返回预构建的实体
"none" (无RETURNING) 即发即弃,最快选项
"col1, col2" RETURNING col1, col2 返回特定列
#[entity(table = "logs", returning = "none")] // 最快
#[entity(table = "users", returning = "full")] // 获取DB生成的值
#[entity(table = "events", returning = "id, created_at")] // 自定义列

upsert(...)(可选)

生成基于 INSERT ... ON CONFLICTupsert 仓库方法。

#[derive(Entity)]
#[entity(table = "users", upsert(conflict = "email"))]
pub struct User {
 #[id]
 pub id: Uuid,
 #[field(create, response)]
 #[column(unique)]
 pub email: String,
 #[field(create, update, response)]
 pub name: String,
}
选项 必需 默认值 说明
conflict 逗号分隔的冲突目标列
action "update" "update"(DO UPDATE)或 "nothing"(DO NOTHING)

生成内容:

  • action = "update"async fn upsert(&self, dto: CreateUserRequest) -> Result<User, Error> — 用新值覆盖所有非冲突列(DO UPDATE SET col = EXCLUDED.col)并返回持久化后的行
  • action = "nothing"async fn upsert(&self, dto: CreateUserRequest) -> Result<Option<User>, Error> — 保留现有行不变;None 表示冲突行已存在

编译期校验:

  • 冲突列必须存在且具有唯一性保证(#[id]#[column(unique)] 或匹配的 unique_index(...))
  • 要求 returning = "full"(默认值)
  • action = "update" 至少需要一个非冲突的可更新列

启用 streams 时,upsert 会为每个返回的行发布 Created 通知。

error(可选)

repository的自定义错误类型。默认:sqlx::Error

#[derive(Debug)]
pub enum AppError {
 Database(sqlx::Error),
 NotFound,
 Validation(String),
}
impl std::error::Error for AppError {}
impl std::fmt::Display for AppError { /* ... */ }
// 必需:从sqlx::Error转换
impl From<sqlx::Error> for AppError {
 fn from(err: sqlx::Error) -> Self {
 AppError::Database(err)
 }
}
#[derive(Entity)]
#[entity(table = "users", error = "AppError")]
pub struct User { /* ... */ }
// 生成的repository使用AppError:
// impl UserRepository for PgPool {
// type Error = AppError;
// ...
// }

events(可选)

生成生命周期事件枚举。详见 事件

#[entity(table = "orders", events)]

生成:

pub enum OrderEvent {
 Created(Order),
 Updated { id: Uuid, changes: UpdateOrderRequest },
 Deleted(Uuid),
}

hooks(可选)

生成生命周期钩子trait。详见 钩子

#[entity(table = "users", hooks)]

生成:

#[async_trait]
pub trait UserHooks: Send + Sync {
 type Error: std::error::Error + Send + Sync;
 async fn before_create(&self, dto: &mut CreateUserRequest) -> Result<(), Self::Error>;
 async fn after_create(&self, entity: &User) -> Result<(), Self::Error>;
 async fn before_update(&self, id: &Uuid, dto: &mut UpdateUserRequest) -> Result<(), Self::Error>;
 async fn after_update(&self, entity: &User) -> Result<(), Self::Error>;
 async fn before_delete(&self, id: &Uuid) -> Result<(), Self::Error>;
 async fn after_delete(&self, id: &Uuid) -> Result<(), Self::Error>;
}

commands(可选)

启用CQRS命令模式。详见 命令

#[entity(table = "users", commands)]
#[command(Register)]
#[command(Deactivate, requires_id)]

字段级属性

应用于单个字段。

#[id]

标记主键字段。

行为:

  • 自动生成UUID(默认v7,可用uuid属性配置)
  • 始终包含在 Response DTO中
  • CreateRequestUpdateRequest 中排除
#[id]
pub id: Uuid,

#[auto]

标记自动生成的字段(时间戳、序列)。

行为:

  • From<CreateRequest> 中获取 Default::default()
  • CreateRequestUpdateRequest 中排除
  • 可通过 #[field(response)] 包含在 Response
#[auto]
#[field(response)]
pub created_at: DateTime<Utc>,

#[field(...)]

控制DTO包含。组合多个选项:

#[field(create)] // 仅在CreateRequest中
#[field(update)] // 仅在UpdateRequest中
#[field(response)] // 仅在Response中
#[field(create, response)] // 在Create和Response中
#[field(create, update, response)] // 在所有三个中
#[field(skip)] // 从所有DTO中排除

create

CreateRequest DTO中包含字段。

#[field(create)]
pub email: String,
// 生成:
pub struct CreateUserRequest {
 pub email: String,
}

update

UpdateRequest DTO中包含字段。

重要: 非可选字段会自动包装在 Option<T> 中以支持部分更新。

#[field(update)]
pub name: String, // 非Option
// 生成:
pub struct UpdateUserRequest {
 pub name: Option<String>, // 自动包装
}

response

Response DTO中包含字段。

#[field(response)]
pub email: String,
// 生成:
pub struct UserResponse {
 pub id: Uuid, // 始终包含(有#[id])
 pub email: String, // 包含
}

skip

所有DTO中排除字段。用于敏感数据。

#[field(skip)]
pub password_hash: String,

重要: skip 覆盖所有其他字段选项。字段仅存在于:

  • 原始实体结构
  • Row 结构(用于数据库读取)
  • Insertable 结构(用于数据库写入)

#[column(pg_enum = "...")]

ValueObject Postgres 枚举接入 DDL 生成。

#[derive(ValueObject, Debug, Clone, Serialize, Deserialize)]
#[value_object(pg_type = "order_status", sqlx)]
pub enum OrderStatus { Pending, Shipped, Delivered }
#[derive(Entity)]
#[entity(table = "orders", migrations)]
pub struct Order {
 #[id]
 pub id: Uuid,
 #[field(create, update, response)]
 #[column(pg_enum = "order_status")]
 pub status: OrderStatus,
}
for ddl in Order::MIGRATION_TYPES {
 sqlx::query(ddl).execute(&pool).await?;
}
sqlx::query(Order::MIGRATION_UP).execute(&pool).await?;
  • 设置 DDL 列类型(否则枚举字段回退为 TEXT)
  • 将枚举的幂等 PG_CREATE_TYPE DDL 注册到 {Entity}::MIGRATION_TYPES — 请在 MIGRATION_UP 之前执行
  • 声明的名称在编译期与枚举的 PG_TYPE 常量核对,不一致会导致构建失败
  • ValueObject 的可选 sqlx 标志会生成 sqlx::Type / Encode / Decode 实现;若已自行 derive sqlx::Type 则省略

#[filter] / #[filter(...)]

生成查询过滤字段。详见 过滤

#[filter] // 精确匹配:WHERE field = $n
#[filter(eq)] // 同上
#[filter(like)] // 模式匹配:WHERE field ILIKE $n
#[filter(range)] // 范围:WHERE field >= $n AND field <= $m

#[belongs_to(Entity)]

外键关系。详见 关系

#[belongs_to(User)]
pub user_id: Uuid,

生成: repository中的 find_user() 方法。

#[has_many(Entity)]

一对多关系(实体级)。详见 关系

#[has_many(Post)]
pub struct User { /* ... */ }

生成: repository中的 find_posts() 方法。

#[projection(Name: fields)]

生成部分视图结构(实体级)。

#[projection(Public: id, name, avatar)]
#[projection(Admin: id, name, email, role)]
pub struct User { /* ... */ }

生成:

  • UserPublic { id, name, avatar }
  • UserAdmin { id, name, email, role }
  • From<User> 实现
  • find_by_id_public()find_by_id_admin() 方法

命令属性

通过 #[command(...)] 应用于实体级。

快速参考

语法 效果
#[command(Name)] 使用所有 #[field(create)] 字段
#[command(Name: field1, field2)] 仅使用指定字段(添加 requires_id)
#[command(Name, requires_id)] 添加ID字段,无其他字段
#[command(Name, source = "create")] 显式使用create字段(默认)
#[command(Name, source = "update")] 使用update字段(可选,添加 requires_id)
#[command(Name, source = "none")] 无payload字段
#[command(Name, payload = "Type")] 使用自定义payload结构
#[command(Name, result = "Type")] 使用自定义结果类型
#[command(Name, kind = "create")] 提示:创建实体(默认)
#[command(Name, kind = "update")] 提示:修改实体
#[command(Name, kind = "delete")] 提示:删除实体(返回 ())
#[command(Name, kind = "custom")] 提示:自定义操作

详见 命令

完整示例

#[derive(Entity)]
#[entity(
 table = "posts",
 schema = "blog",
 sql = "full",
 dialect = "postgres",
 uuid = "v7",
 soft_delete,
 returning = "full",
 events,
 hooks,
 commands
)]
#[has_many(Comment)]
#[projection(Summary: id, title, author_id, created_at)]
#[command(Publish)]
#[command(Archive, requires_id)]
pub struct Post {
 #[id]
 pub id: Uuid,
 #[field(create, update, response)]
 #[filter(like)]
 pub title: String,
 #[field(create, update, response)]
 pub content: String,
 #[field(create, response)]
 #[belongs_to(User)]
 #[filter]
 pub author_id: Uuid,
 #[field(update, response)]
 pub published: bool,
 #[field(response)]
 #[filter(range)]
 pub view_count: i64,
 #[field(skip)]
 pub moderation_notes: String,
 #[field(skip)]
 pub deleted_at: Option<DateTime<Utc>>,
 #[auto]
 #[field(response)]
 #[filter(range)]
 pub created_at: DateTime<Utc>,
 #[auto]
 #[field(response)]
 pub updated_at: DateTime<Utc>,
}

决策矩阵

我想要... 属性
自动生成主键 #[id]
使用随机UUID 实体上 uuid = "v4"
使用时间排序UUID uuid = "v7"(默认)
在POST请求体中接受 #[field(create)]
在PATCH请求体中接受 #[field(update)]
在API响应中返回 #[field(response)]
接受并返回 #[field(create, update, response)]
从所有API隐藏 #[field(skip)]
自动生成时间戳 #[auto] + #[field(response)]
只读(DB管理) #[field(response)]
只写(不返回) #[field(create)]
自定义SQL查询 sql = "trait"
仅DTO,无DB sql = "none"
软删除记录 实体上 soft_delete
自定义错误类型 实体上 error = "MyError"
按精确值过滤 字段上 #[filter]
按模式过滤 字段上 #[filter(like)]
按范围过滤 字段上 #[filter(range)]
跟踪实体变更 实体上 events
在生命周期运行代码 实体上 hooks
使用领域命令 实体上 commands + #[command(...)]
定义关系 #[belongs_to(Entity)]#[has_many(Entity)]
实体部分视图 #[projection(Name: fields)]

🌐 Language

🇬🇧 English | 🇷🇺 Русский | 🇰🇷 한국어 | 🇪🇸 Español | 🇨🇳 中文


🇬🇧 English

Home

Getting Started

Features

Advanced


🇷🇺 Русский

Главная

Начало работы

Возможности

Продвинутое


🇰🇷 한국어

시작하기

기능

고급


🇪🇸 Español

Inicio

Comenzando

Características

Avanzado


🇨🇳 中文

首页

入门

功能

高级


📚 Reference

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /