Files
easygoadmin-wiki/EasyGoAdmin_Gin_NaiveVue/zh/guide/repository.md
T
2026-10-25 17:24:27 +08:00

3.2 KiB
Raw Blame History

3.4 数据访问层(repository)

:::tip 概述 仓储层做一件事:给 service 一个安全的数据库入口。铁律:禁止裸用 *gorm.DB——统一经 repository.NewXxxRepo().Ctx(ctx) 访问,软删过滤与租户隔离自动注入。 :::

标准结构

// 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 附带的便捷方法:

// 软删除(业务删除统一入口,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 入口(受限场景)

repo.Raw(ctx)   // 不注入软删/租户 Scope

Raw() 仅限导入、字典管理、登录校验等明确场景使用——已软删行会进入结果集、跨租户数据可见,条件完整性由使用者自行保证。常规业务查询一律走 Ctx。

事务

// 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)