Go-gorm如果在其他回调中启动删除,则不会调用BeforeDelete回调
我的数据库中有一个分层模型(一个团队有客户,每个客户可以有笔记)。我的目标是能够清理数据库,如果一个团队被删除: - >删除团队 - >删除所有客户 - >删除每个客户的所有笔记Go-gorm如果在其他回调中启动删除,则不会调用BeforeDelete回调
我的计划是用BeforeDelete回调,但在团队回调之后,BeforeDelete for Customers不会被更好地调用。 在数据库中,团队被删除以及其客户,但客户的说明不是。日志行也不会被打印。
您是否知道是否有可能链接这些回调,或者是否设计为第二个回调未执行。
package main
import (
"errors"
"log"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
var DB *gorm.DB
type Team struct {
gorm.Model
Name string
Customers []Customer
}
type Note struct {
gorm.Model
Content string
OwnerID uint
OwnerType string
}
type Customer struct {
gorm.Model
Name string
TeamID uint
Notes []Note `gorm:"polymorphic:Owner;"`
}
func (team *Team) BeforeDelete(tx *gorm.DB) (err error) {
log.Println("------- delete team ---------")
tx.Where("team_id = ?", team.ID).Delete(&Customer{})
return
}
func (customer *Customer) BeforeDelete(tx *gorm.DB) (err error) {
log.Println("------- delete customer ---------")
tx.Where("owner_type = ? AND owner_id = ?", "customers", customer.ID).Delete(&Note{})
return
}
func (note *Note) BeforeDelete(tx *gorm.DB) (err error) {
log.Println("------- delete note ---------")
return
}
func init() {
var err error
DB, err = gorm.Open("sqlite3", "data.DB")
if err != nil {
log.Printf("Error from gorm.Open: %s\n", err)
}
log.Println("You connected to your database.")
if DB.HasTable(&Team{}) {
DB.DropTable(&Team{})
DB.DropTable(&Customer{})
DB.DropTable(&Note{})
}
if !DB.HasTable(&Team{}) {
DB.CreateTable(&Team{})
}
if !DB.HasTable(&Customer{}) {
DB.CreateTable(&Customer{})
}
if !DB.HasTable(&Note{}) {
DB.CreateTable(&Note{})
}
}
func createTeam(name string) Team {
team := Team{Name: name}
DB.Create(&team)
return team
}
func addCustomer(teamID uint, name string) Customer {
customer1 := Customer{Name: name}
customer1.TeamID = teamID
customer1.Notes = []Note{}
DB.Create(&customer1)
return customer1
}
func addNoteToCustomer(customerID uint, note Note) (customer Customer, err error) {
if DB.Preload("Notes").First(&customer, customerID).RecordNotFound() {
return customer, errors.New("customer doesn't exists")
}
customer.Notes = append(customer.Notes, note)
DB.Save(&customer)
return customer, err
}
func main() {
team := createTeam("Team 1")
team2 := createTeam("Team 2")
// Create customers
customer1 := addCustomer(team.ID, "TestC 1")
customer2 := addCustomer(team.ID, "TestC 2")
customer3 := addCustomer(team2.ID, "TestC 3")
customer4 := addCustomer(team2.ID, "TestC 4")
note1 := Note{Content: "testcontent"}
addNoteToCustomer(customer1.ID, note1)
note2 := Note{Content: "testcontent 2"}
addNoteToCustomer(customer2.ID, note2)
note3 := Note{Content: "testcontent 3"}
addNoteToCustomer(customer3.ID, note3)
note4 := Note{Content: "testcontent 4"}
addNoteToCustomer(customer4.ID, note4)
DB.Delete(&team)
}
周围很多努力之后,我已经找到了解决办法:
func (team *Team) BeforeDelete(tx *gorm.DB) (err error) {
//tx.Where("team_id = ?", team.ID).Delete(Customer{})
var customers []Customer
tx.Model(&team).Related(&customers)
for _, customer := range customers {
tx.Delete(&customer)
}
return
}
而且类似的其他车型。如果有人有更好的建议,我很高兴看到它(不知何故,我不喜欢这一个 - 太多的代码)
我认为这是因为BeforeDelete函数被添加到客户模型的指针结构。
您刚刚在第一个示例中传入Customer{}
,这不是指向模型结构的指针。试试下面的例子吗?
var customer Customer
func (team *Team) BeforeDelete(tx *gorm.DB) (err error) {
tx.Where("team_id = ?", team.ID).Delete(&customer)
return
}
感谢您的回复。在第一行('var customer Customer {}“),我得到语法错误,所以我删除了大括号。但不幸的是,它并没有解决原始问题。 在BeforeDelete中,我忘记添加但是即使我这样做,团队也会被删除,客户也会被删除,但客户的笔记不会。 我会尝试将整个脚本添加到问题中,以便任何人都可以测试该行为。 – phev8
这似乎仍然是真实的,即使在2017年,我也对这种行为感到惊讶,对于某人执行'db.Delete(Customer {...})'而不是'db.Delete (&Customer {... {)'。尽管看起来至少有一些尝试总是通过指针类型调用方法:https://github.com/jinzhu/gorm/commit/5174cc5c242a728b435ea2be8a2f7f998e15429b –
它按预期工作,但我不明白主要区别,为什么它比问题中的更好。如果有人能指出,我也很高兴。谢谢。 – phev8