后端数据库ORM【免费下载链接】sea-orm A powerful relational ORM for Rust项目地址https://gitcode.com/gh_mirrors/se/sea-orm点击查看免费下载本指南基于仓库中的examples/proxy_cloudflare_worker_example示例讲解如何在 Cloudflare WorkersRust 版中集成 SeaORM通过proxy代理特性驱动 Cloudflare D1基于 SQLite 的 serverless 数据库并配合 axum 搭建 HTTP 路由。读完本文你将掌握ProxyDatabaseTrait的完整实现套路、D1 值类型与 SeaORMValue的双向映射方法以及整个示例的可运行配置能够据此在自己的 Worker 项目中复刻一套完整的 SeaORM D1 读写链路。示例概览一个以 SeaORM 为核心的 Worker该示例是一个用 Rust 编写的 Cloudflare Worker它以sea-orm作为 ORM 与存储在 Cloudflare D1 中的 SQLite 数据交互以axum作为服务器框架。整个示例的文件结构非常紧凑全部逻辑集中在examples/proxy_cloudflare_worker_example/src/下的 5 个文件中lib.rsWorker 的fetch事件入口负责获取 D1 绑定并建立 SeaORM 连接d1bridge.rs核心桥接层实现ProxyDatabaseTrait让 SeaORM 认识 D1entity.rs定义posts实体模型route.rsaxum 路由与请求处理utility.rs建表工具与错误映射。与普通 SeaORM 项目最大的不同在于这里没有 MySQL/Postgres/SQLite 的原生驱动连接串而是通过Database::connect_proxy把 SeaORM 接到一个自定义的代理数据库实现上即 D1。这一点在后续源码分析中会详细展开。环境准备与快速启动README 明确了运行前提需要安装npm和cargo并建议使用最新版本的nodejs和rust本示例的Cargo.toml声明rust-version 1.85.0、edition 2024。启动开发服务器只需一条命令npx wrangler devnpx wrangler dev会读取项目根目录的wrangler.toml先执行其[build]段定义的构建命令自动安装worker-build并以 release 模式编译 Rust Worker 为 WASM然后启动本地开发服务器并暴露 D1 绑定。首次运行会自动拉取 wrangler 与构建工具需要保持网络可用。wrangler.tomlD1 绑定与构建配置示例的 wrangler.toml 是 Worker 的行为说明书全文如下compatibility_date 2026-03-29 main build/worker/shim.mjs name axum [[d1_databases]] binding D1TEST database_name axumtest # Change it if you want to use your own database database_id 00000000-0000-0000-0000-000000000000 [build] command cargo install -q worker-build worker-build --release逐项说明compatibility_dateWorker 运行时兼容性日期决定可用 API 集合main入口模块指向worker-build产出的 shim 文件build/worker/shim.mjs该文件由构建过程生成无需手写nameWorker 名称示例中为axum[[d1_databases]]声明一个 D1 数据库绑定。binding是代码中通过env.d1(...)取用的键名示例为D1TESTdatabase_name为数据库名称database_id是占位符00000000-0000-0000-0000-000000000000实际部署前必须替换为你自己的 D1 数据库 ID[build]worker-build --release将 Rust 代码编译成 Worker 可加载的 WASM 模块cargo install -q worker-build保证构建工具就绪首次较慢后续有缓存。Cargo.toml让 SeaORM 进入代理模式的关键特性examples/proxy_cloudflare_worker_example/Cargo.toml 中最关键的是 SeaORM 的依赖声明sea-orm { path ../../, default-features false, features [ macros, proxy, with-uuid, with-chrono, with-json, debug-print, ] }proxy本示例的核心开关。它启用Database::connect_proxy与ProxyDatabaseTrait相关 API让 SeaORM 可以对接任意实现了该 trait 的“代理数据库”而不是内置驱动macros提供DeriveEntityModel等派生宏with-uuid/with-chrono/with-json分别为uuid、chrono、serde_json类型实现Value转换实体中的uuid与chrono::Utc::now()字段依赖它们debug-print开启 SQL 调试输出便于在 Worker 控制台观察生成的 SQL。其余依赖与角色的对应关系worker { version 0.7.5, features [http, axum, d1] }Cloudflare Workers Rust 运行时绑定d1feature 提供D1Database类型axum { version 0.8, default-features false, features [macros] }服务器框架tower-service让Router能作为Service被fetch事件调用wasm-bindgen及其 futuresWASM 环境下与 JS 值互操作的基础设施crate-type [cdylib]编译为 WASM 模块所需的库类型。Worker 入口从 fetch 事件到数据库连接src/lib.rs 是请求的起点#[event(fetch)] async fn fetch( req: HttpRequest, env: Env, _ctx: Context, ) - Resultaxum::http::Responseaxum::body::Body, worker::Error { console_error_panic_hook::set_once(); // https://developers.cloudflare.com/d1/worker-api/ let d1 env.d1(D1TEST)?; let db crate::d1bridge::connect_d1(d1) .await .map_err(|e| worker::Error::from(e.to_string()))?; console_log!(Connected to database); Ok(route::router(db).call(req).await?) }执行流程可以拆成四步#[event(fetch)]注册 Worker 的请求处理入口通过env.d1(D1TEST)取出wrangler.toml中声明的 D1 绑定调用d1bridge::connect_d1将其转换为 SeaORM 的DatabaseConnection这一步是整个示例的技术核心构造 axum 路由并调用router(db).call(req)把请求交给 axum 处理返回axum::http::Response。注意console_log!与console_error_panic_hook的使用WASM 环境没有标准输出所有日志都需要通过 Worker 的控制台 API 输出这也是调试 SeaORM 生成 SQL 的主要途径配合debug-print特性。核心桥接层实现 ProxyDatabaseTrait 连接 D1src/d1bridge.rs 是理解整个示例的关键。它先用Database::connect_proxy建立连接struct D1(ArcD1Database); pub async fn connect_d1(d1: D1Database) - ResultDatabaseConnection, DbErr { Database::connect_proxy(DbBackend::Sqlite, Arc::new(Box::new(D1(d1.into())))).await }connect_proxy接收两个参数后端类型这里声明为DbBackend::Sqlite因为 D1 基于 SQLite和ArcBoxdyn ProxyDatabaseTrait形式的代理实现。从 src/database/mod.rs 的源码可以看到该函数按DbBackend分别分发到ProxyDatabaseConnector::connect三种后端MySql/Postgres/Sqlite都受支持意味着 Proxy 模式不限于 D1。随后示例为D1实现了ProxyDatabaseTrait的两个必需方法query查询结果转换async fn query(self, statement: Statement) - ResultVecProxyRow, DbErr { let d1 Arc::clone(self.0); let values map_values(statement); let sql statement.sql; worker::send::SendFuture::new(async move { let res d1.prepare(sql).bind(values)?.all().await?; if let Some(message) res.error() { anyhow::bail!(message.to_string()); } let rows res.results::serde_json::Value()?; anyhow::Ok(rows.into_iter().map(json_to_proxy_row).collect()) }) .await .map_err(|e| DbErr::Exec(RuntimeErr::Internal(e.to_string()))) }要点d1.prepare(sql).bind(values)?.all()是 D1 的预编译查询res.error()用于显式检查 D1 返回的错误信息查询结果以serde_json::Value形式取出后通过json_to_proxy_row转成 SeaORM 的ProxyRow内部是一个BTreeMapString, Value。execute写操作与影响行数async fn execute(self, statement: Statement) - ResultProxyExecResult, DbErr { let d1 Arc::clone(self.0); let values map_values(statement); let sql statement.sql; worker::send::SendFuture::new(async move { let meta d1.prepare(sql).bind(values)?.run().await?.meta()?; let last_insert_id meta.as_ref().and_then(|m| m.last_row_id).unwrap_or(0) as u64; let rows_affected meta.and_then(|m| m.rows_written).unwrap_or(0) as u64; anyhow::Ok(ProxyExecResult { last_insert_id, rows_affected }) }) .await .map_err(|err| DbErr::Conn(RuntimeErr::Internal(err.to_string()))) }execute面向 INSERT/UPDATE/CREATE 等写语句从 D1 的meta()中取出last_row_id自增主键与rows_written受影响行数封装为ProxyExecResult返回。这两个值正是 SeaORM 执行插入后回填自增主键、以及rows_affected判断所依赖的数据。值得留意的是整个 D1 调用被包裹在worker::send::SendFuture::new(...)中这是为了让非Send的 WASM Future 满足 SeaORM 内部对 FutureSend约束的要求是编写 Worker 代理时的必要适配。值映射SeaORM Value 与 D1 JS 值的双向转换SeaORM 的Statement携带Values(VecValue)而 D1 的bind需要 JS 值JsValue。map_values完成了这一转换src/d1bridge.rs其映射规则值得逐类核对布尔与字符Value::Bool/Value::Char直接转换浮点Float、Double经from_f64转换有符号整数BigInt转成字符串避免精度丢失Int/SmallInt/TinyInt直接转换无符号整数BigUnsigned同样转字符串其余直接转换字符串与 JSONString、Json转成字符串形式字节Bytes被格式化为 SQLite 十六进制字面量X...时间类型ChronoDate、ChronoDateTime等 5 种 chrono 类型统一转为字符串其他/空值回退为JsValue::NULL。反向转换由json_to_proxy_row完成D1 返回的 JSON 对象中布尔映射为Value::Bool数字按i64/u64/f64分别映射为BigInt/BigUnsigned/Double字符串映射为Value::String。这套双向映射保证了 SeaORM 的类型系统与 D1 的 JSON 结果集能无缝对接。实体模型与 axum 路由一条完整的读写链路src/entity.rs 定义了一张简单的posts表#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)] #[sea_orm(table_name posts)] pub struct Model { #[sea_orm(primary_key)] pub id: i64, pub title: String, pub text: String, }src/route.rs 中AppState用Arc包装了DatabaseConnection并注册了两个路由Router::new() .route(/, get(handler_get)) .route(/generate, get(handler_generate)) .with_state(state)GET /先ensure_schema确保表存在再用Entity::find().all(state.db)查询全部记录最后serde_json::to_string序列化返回GET /generate构造ActiveModel插入一行数据id使用NotSet交给数据库自增title使用当前 UTC 时间的 RFC3339 字符串text使用uuid::Uuid::new_v4()生成的新 UUID然后insert(state.db)落库。这段代码直接复用了 SeaORM 标准的EntityTrait与ActiveModelTraitAPI——这也正是 Proxy 模式的魅力所在一旦connect_d1建立了连接上游业务代码与使用 MySQL/SQLite 驱动的 SeaORM 项目别无二致。自动建表与错误处理src/utility.rs 提供了两个辅助能力pub async fn ensure_schema(db: DatabaseConnection) - Result(), DbErr { let backend db.get_database_backend(); let stmt Schema::new(backend) .create_table_from_entity(crate::entity::Entity) .if_not_exists() .to_owned(); db.execute(stmt).await?; Ok(()) }ensure_schema借助 SeaORM 的Schema构建器根据实体定义生成CREATE TABLE IF NOT EXISTS posts (...)并通过db.execute执行省去了手工维护建表 SQL 的麻烦。db.get_database_backend()返回DbBackend::Sqlite因此生成的 SQL 是 SQLite 方言与 D1 兼容。map_error则把任意错误统一映射为(StatusCode::INTERNAL_SERVER_ERROR, String)并输出到 Worker 控制台。源码注释特别提醒这是为了示例简洁而采用的简化做法生产环境更推荐实现IntoResponsetrait 来做结构化错误响应。从源码理解 Proxy 连接的本质为了更清晰地理解“代理数据库”在 SeaORM 内部如何工作可以对照 src/driver/proxy.rs 中的ProxyDatabaseConnection实现。它把 SeaORM 执行层的调用原样转发给用户提供的ProxyDatabaseTraitexecute(statement)→ 调用proxy.execute(statement)并包装为ExecResultquery_one/query_all→ 调用proxy.query(statement)将返回的ProxyRow包装为QueryResultQueryResultRow::Proxybegin/commit/rollback→ 透传给proxy的对应方法ping→ 透传给proxy.ping()。也就是说SeaORM 的DatabaseConnection与 D1 之间唯一的契约就是ProxyDatabaseTrait的query、execute两个必需方法外加可选的 begin/commit/rollback/ping。任何能实现这两个方法的存储后端——无论是 D1、GlueSQL 还是其他自定义存储——都能以同样的方式接入 SeaORM 的查询构建器、实体加载器和事务机制。仓库中的 proxy_gluesql_example 就是同一思路的另一实例ProxyDatabaseTrait自身的单元测试则位于 src/database/proxy.rs。部署与后续扩展建议本地npx wrangler dev验证通过后正式部署前需要完成两件事在wrangler.toml的[[d1_databases]]中替换真实的database_id可通过npx wrangler d1 create database_name创建并获取并同步修改database_name用npx wrangler deploy发布 Worker该命令同样会先走[build]流程。在此基础上可以继续扩展的方向包括在map_values中补充更多Value变体的映射如日期时间带时区之外的细分类型在ProxyDatabaseTrait中实现事务方法以支持 SeaORM 事务 API或参照本示例的结构为其他基于 WASM 的边缘数据库实现代理桥接。无论哪种方向d1bridge.rs 提供的“实现 trait → connect_proxy → 复用全套 ORM API”三步走模式都是可复用的通用范本。赞分享后端数据库ORM【免费下载链接】sea-orm A powerful relational ORM for Rust项目地址https://gitcode.com/gh_mirrors/se/sea-orm点击查看免费下载相关推荐EmDash Cloudflare Demo 实战指南在 Workers D1 上运行 Astro 驱动的全栈 CMSEmDash Cloudflare Demo 实战指南在 Workers D1 上运行 Astro 驱动的全栈 CMS 本指南以仓库中的 demos/clCMS后端前端插件系统Cloudflare Workers 测试Miniflare 中模拟 D1 数据库的完整指南Cloudflare Workers 测试Miniflare 中模拟 D1 数据库的完整指南 Miniflare 是 Cloudflare 官方提供的 Wor文档在 Cloudflare Workers 上托管 Rivet Actorsrivetkit/cloudflare-workers 实战指南在 Cloudflare Workers 上托管 Rivet Actorsrivetkit/cloudflare workers 实战指南 Rivet Ac后端AI Agent人工智能流程编排WebSocket上一篇终极指南Theatre.js 缓存策略与持久化机制深度解析下一篇distilbert-base-german-cased vs 原版BERT为什么轻量级模型更适合生产环境创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
filter 和 intercepter(结合苍穹外卖分析) 全局视角:浏览器请求 → Filter(过滤器,Servlet 层) → DispatcherServlet → Interceptor(拦截器,SpringMVC 层) → Controller
返回:Controller → Interceptor → Filter → 浏览… · 2026/9/24 19:15:08
数据清洗实战指南:从脏数据到高质量数据的完整流程与工具选型 做数据这行久了,会发现一个特别扎心的现象:很多团队把精力全花在搭建集群、训练模型、做可视化大屏上,结果模型上线效果稀烂,业务方一句"你们的数是不是有问题"就把整个项目打回原形。我见过太多这样的案例,… · 2026/9/24 19:15:02
Spring Boot+Vue慈善捐赠平台实战:从数据库设计到部署避坑全解析 做慈善捐赠平台这件事,我一开始其实是有点低估的。接这个项目的时候,客户说“就是个捐赠管理系统,后端管数据,前端管展示”,听着挺简单,真拆开做才发现,它既要处理复杂的角色权限(普… · 2026/9/24 19:15:02
OpenRouter替代方案选型指南:本地化、国产云与自建协议栈深度对比 1. 这不是“换一个网站”那么简单:先搞懂OpenRouter到底在解决什么问题OpenRouter这个词最近半年在开发者、AI应用工程师和中小团队技术负责人圈子里出现频率陡增,但很多人点开官网第一反应是:“这不就是个API聚合平台?”——这种… · 2026/9/24 19:55:40
国产PLM选型指南:从需求梳理到实施落地的完整实践 1. 广州制造业为什么现在开始认真谈国产PLM1.1 先搞清楚PLM到底解决什么问题PLM全称Product Lifecycle Management,中文一般叫产品生命周期管理。我每次给广州企业做选型辅导,都会先花半小时把这件事讲透:它不是一个画图软件,也不… · 2026/9/24 19:55:24
从sqlplus到gsql:Shell脚本迁移GaussDB的完整改造指南 上个月接了一个数据库国产化迁移的评估任务,业务 SQL 的兼容性问题提前过了,语法层面基本没有大阻碍。真正让我头疼的是那几十个在生产环境跑了好多年的 Shell 脚本——清一色的 sqlplus 调用,输出格式、退出码判断、SPOOL 文件解析全是按 Or… · 2026/9/24 19:55:05
数据中心微网两阶段鲁棒规划:灵活性建模与复现实践 数据中心微网的规划问题,近两年在EI期刊里出现的频率越来越高,尤其是“两阶段鲁棒优化”这个方向。手里正好在复现一篇相关的论文,题目是“考虑灵活性的数据中心微网两阶段鲁棒规划方法”,折腾了差不多三周,把Matlab代… · 2026/9/24 19:55:05
离线百科、iPad副屏与高颜值Linux:三款开源工具盘活旧设备 最近身边总有人问我三件事:出门在外的车上想查点东西,偏偏手机没信号,有没有离线查资料的办法?家里那台旧iPad除了躺在床头刷视频,还能不能干点正经事?Linux是不是永远跟“黑乎乎的命令行”“丑到没朋友”绑… · 2026/9/24 19:55:05
Oracle数据库控制文件重建实战:从损坏到恢复的完整指南 1. 什么情况需要重建控制文件,而不是傻等数据文件救场控制文件这玩意儿,平时存在感极低,低到很多DBA入职两三年都可能没正眼瞧过它。但它一旦出事,整个数据库直接瘫痪,实例都起不来,连个讨价还价的余地都没… · 2026/9/24 19:55:05
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44