Rust数据库ORM框架SeaORM代码生成器sea-orm-codegen的使用,自动化生成实体模型与数据库交互代码
SeaORM Codegen 使用指南
安装
在项目目录中运行以下Cargo命令:
cargo add sea-orm-codegen
或者在你的Cargo.toml中添加以下行:
sea-orm-codegen = "1.1.14"
基本使用
sea-orm-codegen是SeaORM框架的代码生成器,可以自动从数据库结构生成Rust实体模型和交互代码。以下是完整示例:
use sea_orm_codegen::{DateTimeCrate, OutputFile};
use std::fs;
// 配置代码生成器
let output = sea_orm_codegen::generate_entity(
"postgres://user:pass@localhost:5432/database", // 数据库连接URL
"public", // 数据库schema
OutputFile {
format: true, // 是否格式化生成的代码
with_serde: "derive", // 是否包含serde支持
with_copy_enums: true, // 是否生成可Copy的枚举
date_time_crate: DateTimeCrate::Chrono, // 使用的时间库(Chrono/Time)
expanded_format: false, // 是否使用扩展格式
},
None, // 表过滤条件
).unwrap();
// 将生成的代码写入文件
fs::write("src/entity.rs", output).unwrap();
生成代码示例
生成的代码会包含实体定义和相关操作,例如:
// 这是自动生成的实体模型示例
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "users")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub email: String,
#[sea_orm(column_type = "DateTime")]
pub created_at: DateTime,
#[sea_orm(column_type = "DateTime")]
pub updated_at: DateTime,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(has_many = "super::posts::Entity")]
Posts,
}
impl Related<super::posts::Entity> for Entity {
fn to() -> RelationDef {
Relation::Posts.def()
}
}
高级配置
可以通过配置控制生成代码的多个方面:
let output = sea_orm_codegen::generate_entity(
"postgres://user:pass@localhost:5432/database",
"public",
OutputFile {
format: true,
with_serde: "derive",
with_copy_enums: true,
date_time_crate: DateTimeCrate::Chrono,
expanded_format: true, // 使用扩展格式
},
Some(vec!["users".to_string(), "posts".to_string()]), // 只生成指定表的代码
).unwrap();
完整使用示例
以下是一个完整的项目示例,展示如何使用SeaORM Codegen生成实体代码并在应用中使用:
// 1. 首先创建一个新的Rust项目
// cargo new seaorm-example
// cd seaorm-example
// 2. 添加依赖到Cargo.toml
/*
[dependencies]
sea-orm = { version = "0.10", features = ["sqlx-postgres", "runtime-tokio-rustls"] }
sea-orm-codegen = "1.1.14"
tokio = { version = "1.0", features = ["full"] }
dotenv = "0.15"
*/
// 3. 创建代码生成脚本 generate.rs
use sea_orm_codegen::{DateTimeCrate, OutputFile};
use std::fs;
fn main() {
// 从环境变量读取数据库连接字符串
dotenv::dotenv().ok();
let db_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
// 生成实体代码
let output = sea_orm_codegen::generate_entity(
&db_url,
"public",
OutputFile {
format: true,
with_serde: "derive",
with_copy_enums: true,
date_time_crate: DateTimeCrate::Chrono,
expanded_format: false,
},
None,
).unwrap();
// 写入文件
fs::write("src/entity.rs", output).unwrap();
}
// 4. 创建主程序 main.rs
use sea_orm::Database;
use entity::prelude::*;
use tokio;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 连接数据库
dotenv::dotenv().ok();
let db_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let db = Database::connect(db_url).await?;
// 查询所有用户
let users = User::find().all(&db).await?;
println!("Found {} users", users.len());
Ok(())
}
// 5. 创建mod.rs
pub mod entity;
项目结构
seaorm-example/
├── Cargo.toml
├── src/
│ ├── main.rs
│ ├── mod.rs
│ └── entity.rs (由generate.rs生成)
└── generate.rs (代码生成脚本)
SeaORM Codegen是SeaQL组织维护的项目,主要维护者为Chris Tsang和Billy Chan。
1 回复
SeaORM代码生成器sea-orm-codegen使用指南
简介
SeaORM是一个异步Rust ORM框架,而sea-orm-codegen是其配套的代码生成工具,可以自动从数据库结构生成Rust实体模型和交互代码,大幅提升开发效率。
安装
首先在Cargo.toml中添加依赖:
[dependencies]
sea-orm = { version = "0.12", features = ["sqlx-postgres", "runtime-async-std-native-tls"] }
[build-dependencies]
sea-orm-codegen = "0.12"
基本使用方法
- 创建一个build.rs文件:
use sea_orm_codegen::{EntityTransformer, OutputFile};
use std::{env, fs, path::Path};
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let dest = Path::new(&out_dir).join("entity");
// 数据库连接URL
let url = "postgres://user:pass@localhost:5432/database";
// 生成实体代码
let output = EntityTransformer::transform(url)
.expect("Failed to generate entities");
fs::create_dir_all(&dest).unwrap();
for OutputFile { name, content } in output.files.iter() {
fs::write(dest.join(name), content).unwrap();
}
}
- 在main.rs或lib.rs中引入生成的实体:
mod entity {
include!(concat!(env!("OUT_DIR"), "/entity/mod.rs"));
}
use entity::*;
配置选项
可以通过EntityTransformer
的配置方法自定义生成行为:
let output = EntityTransformer::transform(url)
.with_table_suffix("Table") // 表名后缀
.with_derive("Serialize, Deserialize") // 添加额外derive
.with_date_time_crate("chrono") // 指定日期时间库
.with_lazy_loading(true) // 启用延迟加载
.expect("Failed to generate entities");
示例输出
生成的实体代码示例(假设有users表):
// entity/users.rs
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "users")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub email: String,
#[sea_orm(column_type = "DateTime")]
pub created_at: DateTime,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
使用生成的实体
use entity::users::Entity as Users;
// 查询所有用户
let users = Users::find().all(db).await?;
// 创建新用户
let new_user = users::ActiveModel {
name: Set("John Doe".to_owned()),
email: Set("john@example.com".to_owned()),
..Default::default()
};
new_user.insert(db).await?;
// 条件查询
let user = Users::find()
.filter(users::Column::Email.eq("john@example.com"))
.one(db)
.await?;
高级功能
- 生成枚举类型(如果数据库有枚举列):
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)]
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "user_role")]
pub enum Role {
#[sea_orm(string_value = "admin")]
Admin,
#[sea_orm(string_value = "user")]
User,
}
- 自定义表名映射:
#[derive(Debug, Clone, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "tbl_user")] // 映射到数据库中的tbl_user表
pub struct Model {
// 字段定义
}
完整示例
下面是一个完整的项目结构和使用示例:
- 项目结构:
my_project/
├── Cargo.toml
├── build.rs
├── src/
│ ├── main.rs
│ └── ...
└── migrations/ # 数据库迁移文件(可选)
- Cargo.toml配置:
[package]
name = "my_project"
version = "0.1.0"
edition = "2021"
[dependencies]
sea-orm = { version = "0.12", features = ["sqlx-postgres", "runtime-async-std-native-tls"] }
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
[build-dependencies]
sea-orm-codegen = "0.12"
- build.rs完整示例:
use sea_orm_codegen::{EntityTransformer, OutputFile};
use std::{env, fs, path::Path};
fn main() -> std::io::Result<()> {
let out_dir = env::var("OUT_DIR").unwrap();
let dest = Path::new(&out_dir).join("entity");
// 数据库连接URL - 请替换为实际的数据库连接信息
let url = "postgres://postgres:password@localhost:5432/my_database";
// 生成实体代码并配置选项
let output = EntityTransformer::transform(url)
.with_derive("Serialize, Deserialize")
.with_date_time_crate("chrono")
.expect("Failed to generate entities");
// 创建输出目录
fs::create_dir_all(&dest)?;
// 写入生成的文件
for OutputFile { name, content } in output.files.iter() {
fs::write(dest.join(name), content)?;
}
Ok(())
}
- main.rs完整示例:
mod entity {
include!(concat!(env!("OUT_DIR"), "/entity/mod.rs"));
}
use entity::*;
use sea_orm::{Database, DatabaseConnection, EntityTrait, ActiveModelTrait, ColumnTrait, QueryFilter};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 建立数据库连接
let db: DatabaseConnection = Database::connect("postgres://postgres:password@localhost:5432/my_database").await?;
// 使用生成的实体
let users = entity::users::Entity::find().all(&db).await?;
println!("Found {} users", users.len());
// 创建新用户
let new_user = entity::users::ActiveModel {
name: sea_orm::ActiveValue::Set("Alice".to_owned()),
email: sea_orm::ActiveValue::Set("alice@example.com".to_owned()),
..Default::default()
};
let insert_result = new_user.insert(&db).await?;
println!("Created user with ID: {}", insert_result.id);
// 条件查询
let user = entity::users::Entity::find()
.filter(entity::users::Column::Email.eq("alice@example.com"))
.one(&db)
.await?;
if let Some(user) = user {
println!("Found user: {} - {}", user.name, user.email);
}
Ok(())
}
注意事项
- 确保数据库连接URL正确且有足够权限
- 生成代码会在每次编译时执行,适合开发环境
- 生产环境建议将生成的代码提交到版本控制
- 对数据库结构的修改需要重新生成代码
通过sea-orm-codegen可以大幅减少样板代码编写,让开发者更专注于业务逻辑实现。