签入版本

This commit is contained in:
小蚂蚁云
2026-10-25 17:24:27 +08:00
parent 48911cc08f
commit fdbeae092a
1010 changed files with 30682 additions and 95274 deletions
@@ -0,0 +1,105 @@
# 3.4 数据访问层(repository)
:::tip 概述
仓储层做一件事:给 service 一个安全的数据库入口。**铁律:禁止裸用 `*gorm.DB`**——统一经 `repository.NewXxxRepo().Ctx(ctx)` 访问,软删过滤与租户隔离自动注入。
:::
## 标准结构
```go
// internal/repository/example.go
package repository
import (
"context"
"gorm.io/gorm"
)
// ExampleRepo 案例演示仓储
type ExampleRepo struct {
Base
}
// NewExampleRepo 构造案例演示仓储(表名 = gin_ + 模块名)
func NewExampleRepo() *ExampleRepo {
return &ExampleRepo{Base: NewBase("gin_example")}
}
// Ctx 带 ctx 的查询入口
func (r *ExampleRepo) Ctx(ctx context.Context) *gorm.DB {
return r.Base.Ctx(ctx)
}
```
就这么短——结构、构造、Ctx 三段是每个仓储的固定模板,自定义查询方法按需追加在同文件内。关联表(user_role / role_menu)同样建仓储。
## Base 提供的能力
`Ctx(ctx)` 返回的 `*gorm.DB` 已自动注入:
| 注入项 | 条件 |
|---|---|
| `del_flag = 0` | 所有表——已软删行对查询不可见 |
| `tenant_id IN (0, 自身租户)` | 仅租户白名单表且当前身份非平台级(超管)时 |
Base 附带的便捷方法:
```go
// 软删除(业务删除统一入口,UPDATE del_flag=1)
repo.SoftDelete(ctx, "id", id)
repo.SoftDeleteByID(ctx, id)
// 存在性判断(软删/租户已过滤)
ok, err := repo.ExistsByCond(ctx, "name", name)
```
## GORM 查询写法要点
| 场景 | 写法 |
|---|---|
| 等值条件 | `.Where("col = ?", v)` |
| 非等值 | `.Where("id <> ?", id)` |
| IN 条件 | `.Where("col IN ?", slice)` |
| LIKE | `.Where(col+" LIKE ?", "%"+pat+"%")` |
| 指定列 | `.Select("a,b")` |
| 单行读 map | `.Take(&one)`(one 为 `map[string]any`,判空用 `gorm.ErrRecordNotFound`) |
| 多行读 | `.Find(&rows)`(`[]map[string]any` 或 `*[]*T`) |
| 计数 | `.Count(&n)`(n 为 int64) |
| map 插入 | `.Create(&d)`(d 为 `map[string]any`) |
| map 更新 | `.Where(..).Updates(d)` |
| 分页 | `.Offset((p-1)*size).Limit(size).Find(&list)` |
| 排序 | `.Order("sort, id")` |
| 结构体扫描 | Find 直接扫结构体(无 gorm 标签时按字段名蛇形映射;非列字段加 `gorm:"-"`) |
## Raw 入口(受限场景)
```go
repo.Raw(ctx) // 不注入软删/租户 Scope
```
`Raw()` 仅限**导入、字典管理、登录校验**等明确场景使用——已软删行会进入结果集、跨租户数据可见,条件完整性由使用者自行保证。常规业务查询一律走 `Ctx`。
## 事务
```go
// db.WithTrans:事务内所有 Ctx 查询自动复用事务连接
err := db.WithTrans(ctx, func(ctx context.Context) error {
if err := repoA.Ctx(ctx).Create(&d1).Error; err != nil {
return err // 返回错误自动回滚
}
return repoB.Ctx(ctx).Create(&d2).Error
})
```
事务内务必使用回调入参的 ctx(而非外层 ctx),否则拿不到事务连接。
## 编写检查清单
- [ ] 表名 `gin_` 前缀 + 模块名
- [ ] 只有 Ctx / Raw 两个查询入口,无裸 `*gorm.DB` 字段外泄
- [ ] 删除走 SoftDelete 系列,不写物理 DELETE
- [ ] Raw 使用处有注释说明场景正当性
## 下一步
→ [3.5 业务层开发(service)](/zh/guide/service.html)