GORM 数据访问公共设施:分页查询、逻辑删除、审计字段自动填充。仓库层唯一直接碰 gorm 的地方,service 拿到的是 model 不感知 SQL。写 CRUD 前先读 /crud-guide/repository。
关键导出
PageQuery struct{PageNum, PageSize, OrderByColumn, IsAsc}+NewPageQuery/Num()/Size()/Offset()/Paginate() (Scope)/OrderBy() (clause.OrderBy, error)/HasOrder()PageResult[T] struct{Total int64; Rows []T}+Page(rows, total)/PageOf(rows)/EmptyPage[T]()SelectPage[T](db, q, dest *[]T) (PageResult[T], error)/SelectPageCtx[T](ctx, db, q, dest)LogicDelete struct{DelFlag}(嵌入即获逻辑删除,查/改自动del_flag='0',删改写为UPDATE SET del_flag='1',Unscoped()绕过)AuditUser struct{UserID, DeptID}/WithAuditUser(ctx, u)/AuditUserFrom(ctx)/RegisterAuditCallbacks(db)- 常量
FlagNotDeleted="0" / FlagDeleted="1" / DefaultPageSize=10 / MaxPageSize=500 / AuditDefaultUserID=-1 - 错误
ErrInvalidOrderBy
典型用法
go
// internal/system/service/client_service.go:70
repository.NewClientRepository(database.DB()).SelectPageList(ctx, q, page)
// 模型嵌入逻辑删除
type SysUser struct {
// ...
repository.LogicDelete
}坑/约定
WARNING
SelectPage先 Count 再 Find,用db.Session(&gorm.Session{})克隆 statement 避免SELECT count(*)污染 Find。dest常是 VO 故不能拿 dest 反推表名(会打到不存在的表并丢逻辑删除条件)。- 排序列名用正则白名单防注入(列名无法参数化);
OrderByColumn支持驼峰自动转下划线。 LogicDelete的default:0必须保留(否则插入零值写空串,del_flag='0'查询永远匹配不上)。RegisterAuditCallbacks在database.New内强制调用,审计身份靠WithAuditUser经 ctx 接力(回调只拿得到*gorm.DB);更新回调用SetColumn(Updates(map)的 Dest 是 map,逐行反射覆盖不到)。 :::
相关页:/crud-guide/repository、/pkg-reference/config-database-redis、/conventions/naming。