Soft Delete 软删除扩展
使用官方 softdelete 扩展把软删除字段从核心模型中拆出来,并复用 Oro 的查询、删除、恢复能力。
extensions/softdelete 提供约定软删除字段和字段定义方法。软删除能力仍然走 Oro 的模型查询链路:普通查询自动隐藏已删除数据,OnlyDeleted 查询已删除数据,WithDeleted 取消默认过滤。
import "github.com/duxweb/oro/extensions/softdelete"
安装
软删除扩展没有运行时配置,注册后用于表达项目依赖关系:
db, err := oro.Open(oro.Config{
Connections: map[string]oro.ConnectionConfig{
"default": {Driver: sqlite.Open("app.db")},
},
Extensions: []oro.Extension{
softdelete.Extension(),
},
})
模型字段
推荐直接嵌入 softdelete.SoftDeleteFields:
type Product struct {
oro.Model
softdelete.SoftDeleteFields
Code string
}
func (Product) Define(s *oro.SchemaBuilder) {
s.Table("products")
s.Field("Code").String().Unique()
}
嵌入字段会自动定义约定列 DeletedAt -> deleted_at,类型是 oro.Null[time.Time]。
删除与恢复
_, err := db.Use[Product]().Where("ID", id).Delete(ctx)
模型包含软删除字段时,Delete 会更新 deleted_at,不会物理删除。
product, err := db.Use[Product]().OnlyDeleted().Where("ID", id).First(ctx)
_, err = db.Use[Product]().WithDeleted().Where("ID", id).Restore(ctx)
Restore 会把软删除字段恢复为 NULL。
作用范围
默认过滤(deleted_at IS NULL)现在覆盖所有解析到已注册软删除模型的读取路径,不再只作用于 Use[T]() 模型查询:
- 通过
.With(...)预加载的关联会排除已软删除的关联数据。旧版本会把它们一并返回,现已修复。 - 底层
db.Table("...")读取映射到已注册软删除模型的表时,也会排除已软删除的数据。
模型查询和关联查询仍然保留豁免入口:WithDeleted() 返回包含已删除的数据,OnlyDeleted() 只返回已删除的数据。需要完全不过滤的原生读取时,db.Raw(...) 不会被加上软删除过滤,请按需自行编写条件。
物理删除
需要真正删除记录时使用 ForceDelete:
_, err := db.Use[Product]().Where("ID", id).ForceDelete(ctx)
自定义字段
如果不使用约定字段,可以直接用核心字段构建器标记软删除列:
type Product struct {
oro.Model
RemovedAt oro.Null[time.Time]
}
func (Product) Define(s *oro.SchemaBuilder) {
s.Table("products")
s.Field("RemovedAt").Column("removed_at").Timestamp().SoftDelete()
}