# 12.3 数据访问铁律 :::tip 必须遵守 数据访问的四条红线:**禁止裸用 `*gorm.DB`、一切删除走软删除、Raw 受限使用、事务统一 WithTrans**。违反任何一条都会破坏租户隔离或审计完整性。 ::: ## 铁律一:禁止裸用 *gorm.DB ```go // 正确 repository.NewUserRepo().Ctx(ctx).Where(...).Find(...) // 禁止 db.DB.Where(...) // 全局句柄直用 gorm.Open(...) // 业务层自建连接 ``` `Ctx(ctx)` 是唯一常规入口——软删过滤与租户隔离在此注入,绕过即裸奔。 ## 铁律二:一切删除走软删除 ```go repo.SoftDelete(ctx, "id", id) // UPDATE del_flag=1 repo.SoftDeleteByID(ctx, id) ``` 物理 DELETE 被全局钩子拦截。确需物理清理(定时任务清超期日志): ```go ctx = hooks.WithPhysicalDelete(ctx) // 显式放行,作用域仅此链路 ``` ## 铁律三:Raw 仅限明确场景 `Raw()` 不注入任何 Scope(已删数据可见、跨租户可见),仅限: - 导入(批量落库) - 字典管理(平台级维护) - 登录校验(公开路由无租户身份) 使用处必须注释说明场景正当性,且**条件完整性由使用者自行保证**。 ## 铁律四:事务统一 WithTrans ```go db.WithTrans(ctx, func(ctx context.Context) error { // 回调内一律用入参 ctx(携带事务连接) // 返回非 nil 错误整体回滚 }) ``` 跨模块写操作必须同事务;钩子在事务内同样生效(审计盖章一致)。 ## 常见违反与后果 | 违反 | 后果 | |---|---| | 裸 DB 查询 | 查到已删数据、跨租户数据泄露 | | 业务代码物理删除 | 审计链断裂,无法追责 | | Raw 当常规用 | 同裸 DB,且逐渐扩散 | | 事务用外层 ctx | 事务内查询落回连接池,回滚不生效 | ## 审查抓手 PR 审查 grep 三板斧:`gorm.DB`(层内裸用)、`\.Delete(`(物理删除)、`Raw(`(受限入口)。 ## 相关 - [3.4 数据访问层(repository)](/zh/guide/repository.html) - [4.8 横切机制](/zh/architecture/cross-cutting.html) - [12.6 数据删除规范](/zh/standards/deletion.html)