如果在其他回调中启动删除,则不会调用Go-gorm BeforeDelete回调

时间:2017-09-15 11:39:17

标签: go go-gorm

我的数据库中有一个分层模型(一个团队有客户,每个客户都可以有笔记)。如果团队被删除,我的目标是能够清理数据库: - >删除团队 - >删除所有客户 - >删除每个客户的所有备注

我的计划是使用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)
}

2 个答案:

答案 0 :(得分:1)

我认为这是因为BeforeDelete函数被添加到Customer模型结构的指针中。

您只是在第一个示例中传入Customer{},这不是指向模型结构的指针。请尝试以下示例?

var customer Customer
func (team *Team) BeforeDelete(tx *gorm.DB) (err error) {
    tx.Where("team_id = ?", team.ID).Delete(&customer)
    return
}

答案 1 :(得分:0)

在尝试了很多之后,我找到了一个解决方案:

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
}

同样适用于其他型号。如果有人有更好的建议,我很高兴看到它(不知怎的,我不喜欢这个 - 太多的代码)