news 2026/8/26 15:12:05

ModelManager + Bmc:rust-web-app数据访问层的设计哲学与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ModelManager + Bmc:rust-web-app数据访问层的设计哲学与实战

ModelManager + Bmc:rust-web-app数据访问层的设计哲学与实战

【免费下载链接】rust-web-appCode template for a production Web Application using Axum: The AwesomeApp Blueprint for Professional Web Development.项目地址: https://gitcode.com/gh_mirrors/ru/rust-web-app

rust-web-app 是一个面向生产的 Rust Web 应用脚手架(基于 Axum),它的核心亮点之一就是清晰的数据访问层设计:ModelManager统一管理数据库连接池等数据资源,Bmc(Backend Model Controller)负责每个业务实体的 CRUD 操作,二者通过Dbx组件实现按需开启的数据库事务。本文用通俗的语言带你读懂这套设计哲学,并在实战中展示如何三步给项目新增一个数据实体。

🧩 一图看懂数据访问层的三层分工

rust-web-app 把所有数据访问都收敛到lib-core的 model 模块中(设计说明就在 model/mod.rs 文件头部的注释里),分为三层:

层级角色一句话理解
ModelManager资源管家握着数据库连接池,随请求传入各处使用
Bmc(如UserBmcConvBmc实体管家每个业务表对应一个,封装该表的增删改查
Dbx事务开关决定每次查询走"普通执行"还是"事务执行"

这种分层的最大好处:业务代码永远不直接碰数据库驱动,换库、做压测、写单元测试时只需要盯着这三层改。

🏠 ModelManager:数据资源的"单一入口"

在 model/mod.rs 中,ModelManager结构非常简单,核心就是一个Dbx字段(内部是 sqlx 的 PostgreSQL 连接池,连接池创建逻辑见 store/mod.rs)。

它的设计哲学有三点:

  1. 构造即就绪ModelManager::new()一次性建好连接池(测试环境自动降为 1 连接,规避 tokio 调度抖动,源码注释写得非常坦诚)。
  2. 可共享:实现Clone,在 Axum 中作为 App State 注入所有路由,参考 main.rs 中mm.clone()传入路由的用法。
  3. 可"变身":调用new_with_txn()即可得到一个事务版副本——这是后文事务机制的关键。

📦 Bmc:一个实体一个"控制器"

Bmc全称 Backend Model Controller,比如UserBmc管理user表、ConvBmc管理conv表。每个 Bmc 做两件事:

  • 声明元信息:实现DbBmctrait,指定表名等元数据(定义见 base/mod.rs),例如ConvBmc额外声明has_owner_id()返回true,框架就会在创建时自动写入owner_id
  • 委托通用 CRUD:真正的 SQL 拼装全部委托给 base/crud_fns.rs 里的泛型函数(create/get/list/update/delete),Bmc 自己只写业务特化逻辑。

以 user.rs 为例,UserBmc只声明了const TABLE: &'static str = "user",一行get方法的实现就只是转发到base::get,干净利落。

🔁 Dbx:按需开启的数据库事务(亮点设计)

这套设计最精彩的部分在 store/dbx/mod.rs。默认情况下ModelManager非事务的:每条查询独立执行,简单且快。当业务需要"要么全成功、要么全回滚"时(比如创建用户要先插行再写密码),流程是:

let mm = mm.new_with_txn()?; // 变身事务版 mm.dbx().begin_txn().await?; // 开启事务 // ... 执行多条查询 ... mm.dbx().commit_txn().await?; // 提交

完整实例可搜索mm.dbx().begin_txn(),最佳示范就是 UserBmc::create:先建用户行、再哈希写入密码,两步共享同一个事务。

Dbx内部还有两个值得称道的小设计:

  • 引用计数TxnHolder带 counter,嵌套调用begin_txn只计数不重开事务,commit_txn计数归零才真正提交——避免嵌套事务踩坑。
  • 错误前置:如果误用非事务副本开事务,会立刻返回CannotBeginTxnWithTxnFalse等明确错误(见 dbx/error.rs),而不是静默执行。

⚡ 声明式宏:把样板代码一键清零

手写 Bmc 样板太累?项目提供了generate_common_bmc_fns!宏(定义于 base/macro_utils.rs),一个声明就能生成整套标准 CRUD:

generate_common_bmc_fns!( Bmc: ConvBmc, Entity: Conv, ForCreate: ConvForCreate, ForUpdate: ConvForUpdate, Filter: ConvFilter, );

见 conv.rs:ConvBmc立刻拥有creategetlistcountupdatedelete等全部方法,然后还能追加自定义方法(如add_msg)。重要原则:宏是可选的加分项——需要定制逻辑的实体完全可以手写,甚至只挑部分方法用。

🛠️ 实战:三步新增一个数据实体

以"给项目加一个实体"为例,套路已经完全标准化:

  1. 建表:在 sql/dev_initial/01-create-schema.sql 中建表,统一带上cid/ctime/mid/mtime四个时间戳审计列(框架会自动维护它们)。
  2. 定义类型 + Bmc:在crates/libs/lib-core/src/model/下新建实体文件,声明实体结构、ForCreate/ForUpdate/Filter三种 DTO,然后实现DbBmc并调用generate_common_bmc_fns!
  3. 暴露 RPC 接口:在 web-server 的 rpcs 目录 中用配套的generate_common_rpc_fns!宏生成 JSON-RPC 端点,路由自动挂载到/api

想快速看完整链路?直接跑 quick_dev.rs 示例,它演示了ModelManager初始化、登录、实体 CRUD 的全流程。

📝 总结:这套设计哲学教会我们的事

  • 单一入口:所有数据访问必须穿过 Model 层,资源(连接池、未来的 S3/Redis 客户端)集中在ModelManager
  • 按需事务:默认非事务保性能,new_with_txn()+ 引用计数事务让"开启事务"成为一行显式决策,而非全局默认。
  • 约定大于配置:通用 CRUD 下沉到泛型函数,声明式宏消灭样板,但始终保留"手写逃生舱"。
  • 面向测试:连接池在测试态自动收敛、#[cfg(test)]精细控制,单元测试就是活文档(user.rs 底部测试 覆盖了创建、查询与清理)。

如果你正在用 Rust + Axum 搭建生产级 Web 应用,这套ModelManager + Bmc + Dbx的分层,值得作为你数据访问层设计的蓝本参考。

【免费下载链接】rust-web-appCode template for a production Web Application using Axum: The AwesomeApp Blueprint for Professional Web Development.项目地址: https://gitcode.com/gh_mirrors/ru/rust-web-app

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/26 15:12:03

CSP-J 初赛(以满分为目标):第八课《数组、字符串与常见数据结构——程序里的“储物柜”:一格一格存数据》

第八课 数组、字符串与常见数据结构——程序里的“储物柜”:一格一格存数据这一课是从“单个变量”走向“一组数据”的关键一步。本课要解决一个新问题:如果我要同时保存100个、1000个数据怎么办?这就进入了数组、字符串以及线性数据结构。一…

作者头像 李华
网站建设 2026/8/26 15:05:53

YiShaAdmin 权限管理系统部署指南:4 个高频卡点一次打通

YiShaAdmin 权限管理系统部署指南:4 个高频卡点一次打通 【免费下载链接】YiShaAdmin 基于 .NET Core MVC 的权限管理系统,代码易读易懂、界面简洁美观 项目地址: https://gitcode.com/GitHub_Trending/yi/YiShaAdmin YiShaAdmin 是一个基于 .NET…

作者头像 李华
网站建设 2026/8/26 15:05:44

产品教程|Memmy 如何接续任务查询,并处理本地检索超时

本文经 AI 创作者 Berryxia.AI 授权,根据其实际测试过程整理与改写。 SalesScout 是 Barry 的本地项目,文中的文件名称、查询条件和返回结果来自他的设备和真实项目案例。 Memmy 是运行在本地的个人 AI Agent,同时也是多个 Agent 共用的个人记…

作者头像 李华
网站建设 2026/8/26 15:05:30

EasyMocap 实时 3D 可视化 3 步跑通

EasyMocap 实时 3D 可视化 3 步跑通 【免费下载链接】EasyMocap Make human motion capture easier. 项目地址: https://gitcode.com/gh_mirrors/ea/EasyMocap 算完几百帧姿态,还得翻 json 逐帧核对?EasyMocap 的实时 3D 可视化把关键点直接送进…

作者头像 李华