Documentation
¶
Overview ¶
Package gormx 提供 GORM 数据库客户端封装。
统一封装:自定义 Logger、连接池配置。 零可观测性副作用:构造不注入任何 tracing 插件。
快速接入 ¶
基本用法:
db, err := gorm.Open(mysql.Open(dsn))
if err != nil {
log.Fatal(err)
}
自定义连接池:
db, err := gorm.OpenWithPool(mysql.Open(dsn),
10, // maxIdleConns
100, // maxOpenConns
30*time.Minute, // connMaxLifetime
)
OTel 追踪(装饰器显式接入) ¶
本包不做任何 tracing 注入。需要 SQL Span 时 用 github.com/oekit/tracing/gormotel 显式挂载(无 SDK 时 noop):
db, err := gormx.Open(mysql.Open(dsn))
if err := db.Use(gormotel.NewPlugin(gormotel.WithDBName("mydb"))); err != nil {
return err
}
自定义 Logger ¶
默认使用内置 Logger,支持:
- 慢查询阈值:默认 200ms
- 日志级别:默认 Info
Index ¶
- func InTransactionContext(ctx context.Context, db *gorm.DB, fn TXFunc) error
- func IsUniqueViolation(err error) bool
- func Open(dialector gorm.Dialector, opts ...OpenOption) (*gorm.DB, error)
- func OpenMySQL(cfg MySQLConfig) (*gorm.DB, error)
- func PaginateScope(req *pagination.PageRequest) func(db *gorm.DB) *gorm.DB
- type AuditModel
- type AuditPlugin
- type BaseModel
- type FilterBuilder
- type Logger
- func (l *Logger) Error(ctx context.Context, msg string, data ...any)
- func (l *Logger) Info(ctx context.Context, msg string, data ...any)
- func (l *Logger) LogMode(level gormLogger.LogLevel) gormLogger.Interface
- func (l *Logger) Trace(ctx context.Context, begin time.Time, ...)
- func (l *Logger) Warn(ctx context.Context, msg string, data ...any)
- type Model
- type MySQLConfig
- type OpenOption
- type PageResponse
- type SingletonRepo
- type SoftDeleteModel
- type TXFunc
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func InTransactionContext ¶
InTransactionContext 在带有 context 的数据库事务中执行指定函数。
func IsUniqueViolation ¶
IsUniqueViolation 判断给定 error 是否为唯一键冲突。
func Open ¶
Open 使用指定的 dialector 打开数据库连接,自动注入默认日志。
默认行为:
- 注入默认 Logger(Info 级别)
- 零 tracing 注入:需要 SQL Span 经 github.com/oekit/tracing/gormotel 显式挂载
可通过选项配置连接池等:
db, err := gormx.Open(
mysql.Open(dsn),
gormx.WithConnectionPool(10, 100, time.Hour),
)
需要 OTel 追踪时(装饰器显式接入,无 SDK 时 noop):
db, err := gormx.Open(mysql.Open(dsn))
if err := db.Use(gormotel.NewPlugin()); err != nil { ... }
func OpenMySQL ¶
func OpenMySQL(cfg MySQLConfig) (*gorm.DB, error)
OpenMySQL 从配置创建 GORM DB 实例(含连接池配置;零 tracing 注入, 需要 SQL Span 经 github.com/oekit/tracing/gormotel 显式挂载)。
用法:
db, err := gormx.OpenMySQL(gormx.MySQLConfig{
Host: cfg.Database.Host, Port: cfg.Database.Port,
User: cfg.Database.User, Password: cfg.Database.Password,
DBName: cfg.Database.DBName,
MaxIdleConns: 10, MaxOpenConns: 100,
})
func PaginateScope ¶
func PaginateScope(req *pagination.PageRequest) func(db *gorm.DB) *gorm.DB
PaginateScope 返回一个 GORM Scope 函数,自动应用分页的 Offset 和 Limit。
Types ¶
type AuditModel ¶
type AuditModel struct {
ID int64 `gorm:"primaryKey" json:"id"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"`
CreatedBy int64 `json:"created_by"`
UpdatedBy int64 `json:"updated_by"`
}
AuditModel 是带审计字段的基础模型。 除了软删除外,还包含 created_by 和 updated_by 字段。
type AuditPlugin ¶
type AuditPlugin struct {
// UserIDFunc 从 context 提取当前用户 ID。
UserIDFunc func(ctx context.Context) int64
}
AuditPlugin 是 GORM 审计插件,自动填充 created_by/updated_by 字段。 实体必须包含 CreatedBy 和 UpdatedBy 字段。
func NewAuditPlugin ¶
func NewAuditPlugin(userIDFunc func(ctx context.Context) int64) *AuditPlugin
NewAuditPlugin 创建审计插件。 userIDFunc 从 context 提取当前用户 ID 的函数。
func (*AuditPlugin) Initialize ¶
func (p *AuditPlugin) Initialize(db *gorm.DB) error
Initialize 初始化插件,注册 GORM 回调。
type BaseModel ¶
type BaseModel struct {
ID int64 `gorm:"primaryKey" json:"id"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
}
BaseModel 是通用基础模型,包含 ID 和时间戳。 嵌入此结构体后,实体自动获得主键和时间戳字段。
type FilterBuilder ¶
type FilterBuilder struct {
// contains filtered or unexported fields
}
FilterBuilder 构建动态 SQL WHERE 条件。 适用于查询参数可选的场景,避免大量 if-else 拼接。
用法:
fb := gormx.NewFilterBuilder() fb.Add(opts.Provider != "", "provider = ?", opts.Provider) fb.Add(opts.Repo != "", "repo ILIKE ?", "%"+opts.Repo+"%") fb.Add(!opts.From.IsZero(), "created_at >= ?", opts.From) db = fb.Apply(db)
func (*FilterBuilder) Add ¶
func (fb *FilterBuilder) Add(ok bool, sql string, args ...any) *FilterBuilder
Add 条件为 true 时追加 WHERE 子句。
func (*FilterBuilder) Apply ¶
func (fb *FilterBuilder) Apply(db *gorm.DB) *gorm.DB
Apply 将构建的条件应用到 GORM 查询链。 每个条件之间用 AND 连接。
func (*FilterBuilder) Clauses ¶
func (fb *FilterBuilder) Clauses() (string, []any)
Clauses 返回合并后的子句字符串和参数(用于 raw SQL 场景)。
type Logger ¶
type Logger struct {
gormLogger.Config
// contains filtered or unexported fields
}
Logger 是基于 logx 的 GORM 日志适配器,实现 gormLogger.Interface 接口。 通过 logx 门面输出,支持 slog 结构化日志和 trace_id 传播。
func NewDefaultLogger ¶
func NewDefaultLogger() *Logger
NewDefaultLogger 创建带有合理默认配置(慢查询阈值 200ms、Info 级别)的 Logger。
func NewLogger ¶
func NewLogger(config gormLogger.Config) *Logger
NewLogger 根据给定的配置创建 Logger 实例。 内部持有 Delegating logger 懒解析默认后端:构造(gormx.Open)先于业务 logx.SetDefault 时,SQL 日志仍能跟随运行期切换的后端,不会固化到构造 时刻的 Default。
func (*Logger) LogMode ¶
func (l *Logger) LogMode(level gormLogger.LogLevel) gormLogger.Interface
LogMode 返回一个设置了新日志级别的 Logger 副本。
type MySQLConfig ¶
type MySQLConfig struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
User string `yaml:"user"`
Password string `yaml:"password"`
DBName string `yaml:"dbname"`
MaxIdleConns int `yaml:"max_idle_conns"`
MaxOpenConns int `yaml:"max_open_conns"`
ConnMaxLifeMin int `yaml:"conn_max_life_min"`
}
MySQLConfig 是 MySQL 连接配置,可直接从 YAML 反序列化。
type OpenOption ¶
type OpenOption func(*openConfig)
OpenOption 配置 Open 的行为(函数选项模式)。
func WithConnMaxIdleTime ¶
func WithConnMaxIdleTime(d time.Duration) OpenOption
WithConnMaxIdleTime 配置连接最大空闲时间。 空闲超过此时间的连接会被关闭,防止 stale 连接积累。
func WithConnectionPool ¶
func WithConnectionPool(maxIdleConns, maxOpenConns int, connMaxLifetime time.Duration) OpenOption
WithConnectionPool 配置连接池参数(避免 OpenWithPool 的位置参数易错问题)。
func WithGormOptions ¶
func WithGormOptions(opts ...gorm.Option) OpenOption
WithGormOptions 追加底层 gorm.Option。
type PageResponse ¶
type PageResponse[T any] = pagination.PageResponse[T]
PageResponse 分页查询的响应结果(pkg/pagination 统一信封的别名)。 字段为 Items(JSON "items"),与 crud、hertz/crudh 的契约统一为 pkg/pagination.PageResponse。
func Paginate ¶
func Paginate[T any](db *gorm.DB, req *pagination.PageRequest, queryFn func(db *gorm.DB) *gorm.DB) (*PageResponse[T], error)
Paginate 执行分页查询,返回指定类型的分页结果。 queryFn 只调用一次(GORM 的 *gorm.DB 是不可变的,每次方法调用返回新实例)。
type SingletonRepo ¶
type SingletonRepo[T Model] struct { // contains filtered or unexported fields }
SingletonRepo 提供单例记录的 get-or-default + upsert 模式。 适用于全局配置、系统设置等只有一条记录的场景。
主键列名通过 GORM schema 解析(不硬编码 "id"),主键列名非 id 的模型 同样可用;解析失败时 Get/Save/GetOrCreate 返回错误。
用法:
type MyConfig struct { gormx.BaseModel; Value string }
// MyConfig 通过嵌入 BaseModel 自动获得 GetID/SetID,满足 Model 接口
repo := gormx.NewSingletonRepo(db, func() *MyConfig { return &MyConfig{Value: "default"} })
cfg, err := repo.Get(ctx)
cfg.Value = "updated"
err = repo.Save(ctx, cfg)
func NewSingletonRepo ¶
func NewSingletonRepo[T Model](db *gorm.DB, defaultVal func() T) *SingletonRepo[T]
NewSingletonRepo 创建单例仓库。 defaultVal 返回当记录不存在时的默认值。
func (*SingletonRepo[T]) Get ¶
func (r *SingletonRepo[T]) Get(ctx context.Context) (T, error)
Get 获取唯一的记录。不存在时返回 defaultVal() 的结果,不返回 error。
func (*SingletonRepo[T]) GetOrCreate ¶
func (r *SingletonRepo[T]) GetOrCreate(ctx context.Context) (T, error)
GetOrCreate 获取记录,不存在时创建默认值并返回。 在事务中使用 SELECT ... FOR UPDATE 锁定行。与 Save 相同:FOR UPDATE 锁不住空表并发插入的幻影,Create 撞唯一约束时重读收敛(最多重试一次); 单例表建议加唯一约束作为最终防线。
type SoftDeleteModel ¶
type SoftDeleteModel struct {
ID int64 `gorm:"primaryKey" json:"id"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"`
}
SoftDeleteModel 是带软删除的基础模型。 Delete 操作会设置 deleted_at 而非物理删除。