如何使用软删除设置关联 deletedAt 字段?

How to set associations deletedAt fields with soft delete?

我应该如何使用软删除删除我的关联?

我有以下结构

type PrivateGormModel struct {
    ID        uint       `gorm:"primaryKey" json:"id,string"`
    CreatedAt time.Time  `json:"-"`
    UpdatedAt time.Time  `json:"-"`
    DeletedAt *time.Time `gorm:"index" json:"-"`
}

type Relation struct {
    PrivateGormModel
    OwnerID      uint          `json:"ownerID"`
    OwnerType    string        `json:"ownerType"`
    Addresses    []Address     `gorm:"polymorphic:Owner;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"addresses"`
    Contacts     []Contact     `gorm:"polymorphic:Owner;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"contacts"`
    People       []Person      `gorm:"polymorphic:Owner;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"people"`
    BankAccounts []BankAccount `gorm:"polymorphic:Owner;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"bankAccounts"`
}

type Company struct {
    PrivateGormModel
    Name     string   `json:"name"`
    Relation Relation `gorm:"polymorphic:Owner;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"relation"`
}

我省略了地址、联系人、个人和银行帐户结构以保持此 post 简短,但它们是具有 OwnerIDOwnerType 的简单结构。以及以下处理程序

func DeleteCompany(db *database.Database) fiber.Handler {
    return func(c *fiber.Ctx) error {
        id, err := IDFromParams(c)

        if err != nil {
            return c.JSON(responseKit.ParameterMissing())
        }

        toDelete := new(model.Company)
        result := db.Preload("Relation.Addresses").
            Preload("Relation.Contacts").
            Preload("Relation.People").
            Preload("Relation.BankAccounts").
            Preload(clause.Associations).
            First(toDelete, id)

        fmt.Printf("\n%v", toDelete)

        result = db.Select("Relation.Addresses").
            Select("Relation.Contacts").
            Select("Relation.People").
            Select("Relation.BankAccounts").
            Select("Relation").
            Debug().
            Delete(toDelete)
        if result.Error != nil {
            return c.JSON(responseKit.RecordDeleteError())
        }

        return c.JSON(responseKit.RecordDeleteSuccess())
    }
}

打印输出的位置

{PrivateGormModel:{ID:5 CreatedAt:2021-01-15 11:24:03.672857 +0100 CET UpdatedAt:2021-01-15 11:24:03.672857 +0100 CET DeletedAt:<nil>} Name:Test Relation:{PrivateGormModel:{ID:5 CreatedAt:2021-01-15 11:24:03.738351 +0100 CET UpdatedAt:2021-01-15 11:24:03.738351 +0100 CET DeletedAt:<nil>} OwnerID:5 OwnerType:companies Addresses:[{PrivateGormModel:{ID:5 CreatedAt:2021-01-15 11:24:03.739322 +0100 CET UpdatedAt:2021-01-15 11:24:03.739322 +0100 CET DeletedAt:<nil>} OwnerID:5 OwnerType:relations Country:AA Zip:1111AB Number:1 Addition: Street:Test State:Test City:Test}] Contacts:[{PrivateGormModel:{ID:5 CreatedAt:2021-01-15 11:24:03.740319 +0100 CET UpdatedAt:2021-01-15 11:24:03.740319 +0100 CET 
DeletedAt:<nil>} OwnerID:5 OwnerType:relations Tel:0612345678 Mail:test@test.com URL:}] People:[] BankAccounts:[{PrivateGormModel:{ID:5 CreatedAt:2021-01-15 11:24:03.740319 +0100 CET UpdatedAt:2021-01-15 11:24:03.740319 +0100 CET DeletedAt:<nil>} OwnerID:5 OwnerType:relations Bank:test BIC:test IBAN:test AccountHolder: Establishment:test}]}}

并且调试调试以下内容

DELETE FROM "relations" WHERE "relations"."owner_type" = 'companies' AND "relations"."owner_id" = 5
DELETE FROM "companies" WHERE "companies"."id" = 5

所以关系被删除了。但它对 hasMany 关系没有任何作用。我读了这个

https://gorm.io/docs/associations.html#Delete-with-Select

并尝试这样做,因为约束似乎没有任何作用,但似乎没有任何作用并删除了地址、联系人、人员和银行帐户。我应该如何软删除公司的所有关系?

我用最新版本的 Gorm 测试过,Select 和 Delete 仅适用于一级关联。

如果你这样做了

db.Select("Relation").Delete(toDelete)

您会看到 Company 和 Relation 都将其 DeletedAt 设置为当前时间戳。

要实现二级关系的软删除,您需要在单独的调用中删除它们:

db.Select("Addresses", "Contacts", "People", "BankAccounts").Delete(toDelete.Relation)
// or more compactly
db.Select(clause.Associations).Delete(toDelete.Relation)

可能还值得问问自己,仅软删除模型树的根,而将其他所有内容保持原样是否不足以满足您的用例。