如何级联(软)删除在GORM中有很多关系?

How to cascade (soft) delete has many relationships in GORM?

我正在使用 GORM 实现一些删除功能。我的想法是级联删除,当父行被删除时,子行也被删除。我试过 delete with select。但它只会删除父记录。

func DeleteProject(db *gorm.DB, id uint) (Project, error) {
    var project Project
    if err := db.Select(clause.Associations).Delete(&project, id).Error; err != nil {
        return Project{}, err
    }
    return project, nil
}

我有以下型号:

type Project struct {
    ID           uint           `gorm:"primary_key" json:"id"`
    CreatedAt    time.Time      `json:"created_at"`
    UpdatedAt    time.Time      `json:"updated_at"`
    DeletedAt    gorm.DeletedAt `gorm:"index" json:"deleted_at"`
    TicketNumber string         `gorm:"size:6;unique;not null" json:"ticketnumber"`
    Name         string         `json:"name"`
    MailingList  string         `json:"mailinglist"`
    Environment  string         `gorm:"not null" json:"environment"`
    UserID       uint           `gorm:"index" json:"user_id"`
    Diagrams     []Diagram      `json:"diagrams"`
}

type Diagram struct {
    ID        uint           `gorm:"primary_key" json:"id"`
    CreatedAt time.Time      `json:"created_at"`
    UpdatedAt time.Time      `json:"updated_at"`
    DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
    Data      string         `json:"data"`
    ProjectID uint           `gorm:"index" json:"project_id"`
    Instances []Instance     `json:"instances"`
}

type Instance struct {
    ID        uint           `gorm:"primary_key" json:"id"`
    CreatedAt time.Time      `json:"created_at"`
    UpdatedAt time.Time      `json:"updated_at"`
    DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
    Key       uint           `json:"key"`
    DiagramID uint           `gorm:"index" json:"diagram_id"`
}

一个项目可以有多个图表,一个图表可以有多个实例。但是当我 运行 DeleteProject 函数时,它只删除 Project 而不是相关的图表和实例。

在这种情况下,如何删除项目及其关联的图表和实例?

我找到了解决方案,但我认为它不是级联删除的最佳选择,它至少解决了我的问题。我编写了以下代码:

首先是 DeleteProject 函数,我在其中遍历所有 Diagrams 并调用 DeleteDiagram 函数,最后我还在删除项目之前清除了与该项目的所有关联。

//Delete a project and it's associations.
func DeleteProject(db *gorm.DB, id uint) (Project, error) {
    project, err := GetProject(db, id)
    if err != nil {
        return Project{}, err
    }
    if len(project.Diagrams) > 0 {
        for _, projectDiagram := range project.Diagrams {
            _, err := DeleteDiagram(db, projectDiagram.ID)
            if err != nil {
                return Project{}, err
            }
        }
        db.Model(&project).Association("Diagrams").Clear()
    }
    if err := db.Delete(&project, id).Error; err != nil {
        return Project{}, err
    }
    return project, nil
}

DeleteDiagram 做同样的事情,但是 Instances

//Delete a diagram and it's associations.
func DeleteDiagram(db *gorm.DB, id uint) (Diagram, error) {
    var diagram, err = GetDiagram(db, id)
    if err != nil {
        return Diagram{}, err
    }
    if len(diagram.Instances) > 0 {
        db.Model(&diagram).Association("Instances").Clear()
        for _, diagramInstance := range diagram.Instances {
            _, err := DeleteInstance(db, diagramInstance.ID)
            if err != nil {
                return Diagram{}, err
            }
        }
    }
    if err := db.Delete(&diagram).Error; err != nil {
        return Diagram{}, err
    }
    return diagram, nil
}

希望对您有所帮助。