3 回答
TA贡献1921条经验 获得超9个赞
经过大量的挖掘和调试,我想出了这个解决方案:
您首先需要以正确的顺序注册您的插件执行,在我的情况下应该是这样的:
gormDb.Callback().Create().Before("gorm:commit_or_rollback_transaction").Register("changelog_create", ChangelogCreatePlugin)
此命令将保证您的插件将在模型的任何插入子句的事务提交之前被激活或触发。
要了解有关在何处注册插件的更多信息,请查看在 gorm 中注册的默认回调
这样做之后,我需要调整插件代码:
func ChangelogCreatePlugin(db *gorm.DB) {
// first make a check that the model insert transaction doesn't have any error
if db.Error != nil {
return
}
log := &Log{NewValue: "the new value", OldValue: "the old value", CreatedAt: "current time"}
// get a new db session for the new model to work
logDb := db.Session(&gorm.Session{})
// if an error ocurred while saving the log
// push it into original model db instance errors, so it will be rolledback eventually
logErr := logDb.Save(log)
if logErr != nil {
db.AddError(logErr)
}
}
希望有一天这可以帮助某人!
TA贡献1821条经验 获得超4个赞
尝试创建事务性decorator女巫使用func(d *gorm.DB)或f ...func(d *gorm.DB)作为参数。它应该看起来像
type TransactionalDecorator struct {
DB *gorm.DB
}
func (t *TransactionalDecorator) Transaction(f ...func(d *gorm.DB) error) error {
return t.DB.Transaction(func(tx *gorm.DB) error {
for _, fn := range f {
if err := fn(tx); err != nil {
return err
}
}
return nil
})
}
所有数据库交互功能将在同一个事务中执行
repo , _ := gorm.Open(...)
tdb := &TransactionalDecorator{DB: repo}
saveModel := func(d *gorm.DB) error {
// save model
}
saveLog := func(d *gorm.DB) error {
// save log
}
err := tdb.Transaction(saveModel, saveLog)
TA贡献1828条经验 获得超3个赞
怎么样:
func ChangelogCreatePlugin(db *gorm.DB) {
log := &Log{NewValue: "the new value", OldValue: "the old value", CreatedAt: "current time"}
// Here is the problem
db.Session(&gorm.Session{}).Save(log)
}
这应该给你一个“新鲜”的 db/tx 来使用
- 3 回答
- 0 关注
- 179 浏览
添加回答
举报