-
-
Notifications
You must be signed in to change notification settings - Fork 0
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命令模式 |
数据库表名。
#[entity(table = "users")] // → FROM users #[entity(table = "user_profiles")] // → FROM user_profiles
数据库模式。默认:"public"。
#[entity(table = "users")] // → FROM public.users #[entity(table = "users", schema = "core")] // → FROM core.users #[entity(table = "users", schema = "auth")] // → FROM auth.users
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")] // 完全无数据库层
SQL生成的数据库方言。默认:"postgres"。
| 方言 | 别名 | 客户端类型 | 状态 |
|---|---|---|---|
"postgres" |
"pg", "postgresql"
|
sqlx::PgPool |
稳定 |
"clickhouse" |
"ch" |
clickhouse::Client |
计划中 |
"mongodb" |
"mongo" |
mongodb::Client |
计划中 |
自动生成主键的UUID版本。默认:"v7"。
| 版本 | 方法 | 属性 |
|---|---|---|
"v7" |
Uuid::now_v7() |
时间排序,可排序(推荐) |
"v4" |
Uuid::new_v4() |
随机,广泛兼容 |
#[entity(table = "users", uuid = "v7")] // 时间排序(默认) #[entity(table = "sessions", uuid = "v4")] // 随机UUID
为什么选择UUID v7?
- 时间排序:按创建时间自然排序
- 更好的数据库索引性能
- 无需协调(不像序列)
- 在分布式系统中全局唯一
启用软删除,将记录标记为已删除而不是移除它们。
#[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()— 包含已删除的记录
控制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")] // 自定义列
生成基于 INSERT ... ON CONFLICT 的 upsert 仓库方法。
#[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 通知。
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; // ... // }
生成生命周期事件枚举。详见 事件。
#[entity(table = "orders", events)]生成:
pub enum OrderEvent { Created(Order), Updated { id: Uuid, changes: UpdateOrderRequest }, Deleted(Uuid), }
生成生命周期钩子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>; }
启用CQRS命令模式。详见 命令。
#[entity(table = "users", commands)] #[command(Register)] #[command(Deactivate, requires_id)]
应用于单个字段。
标记主键字段。
行为:
- 自动生成UUID(默认v7,可用
uuid属性配置) - 始终包含在
ResponseDTO中 - 从
CreateRequest和UpdateRequest中排除
#[id] pub id: Uuid,
标记自动生成的字段(时间戳、序列)。
行为:
- 在
From<CreateRequest>中获取Default::default() - 从
CreateRequest和UpdateRequest中排除 - 可通过
#[field(response)]包含在Response中
#[auto] #[field(response)] pub created_at: DateTime<Utc>,
控制DTO包含。组合多个选项:
#[field(create)] // 仅在CreateRequest中 #[field(update)] // 仅在UpdateRequest中 #[field(response)] // 仅在Response中 #[field(create, response)] // 在Create和Response中 #[field(create, update, response)] // 在所有三个中 #[field(skip)] // 从所有DTO中排除
在 CreateRequest DTO中包含字段。
#[field(create)] pub email: String, // 生成: pub struct CreateUserRequest { pub email: String, }
在 UpdateRequest DTO中包含字段。
重要: 非可选字段会自动包装在 Option<T> 中以支持部分更新。
#[field(update)] pub name: String, // 非Option // 生成: pub struct UpdateUserRequest { pub name: Option<String>, // 自动包装 }
在 Response DTO中包含字段。
#[field(response)] pub email: String, // 生成: pub struct UserResponse { pub id: Uuid, // 始终包含(有#[id]) pub email: String, // 包含 }
从所有DTO中排除字段。用于敏感数据。
#[field(skip)] pub password_hash: String,
重要: skip 覆盖所有其他字段选项。字段仅存在于:
- 原始实体结构
-
Row结构(用于数据库读取) -
Insertable结构(用于数据库写入)
生成查询过滤字段。详见 过滤。
#[filter] // 精确匹配:WHERE field = $n #[filter(eq)] // 同上 #[filter(like)] // 模式匹配:WHERE field ILIKE $n #[filter(range)] // 范围:WHERE field >= $n AND field <= $m
外键关系。详见 关系。
#[belongs_to(User)] pub user_id: Uuid,
生成: repository中的 find_user() 方法。
一对多关系(实体级)。详见 关系。
#[has_many(Post)] pub struct User { /* ... */ }
生成: repository中的 find_posts() 方法。
生成部分视图结构(实体级)。
#[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)] |
🇬🇧 English | 🇷🇺 Русский | 🇰🇷 한국어 | 🇪🇸 Español | 🇨🇳 中文
Getting Started
Features
Advanced
Начало работы
Возможности
Продвинутое
시작하기
기능
고급
Comenzando
Características
Avanzado
入门
功能
高级