Golang GORM级联删除嵌套字段

huangapple go评论86阅读模式
英文:

Golang GORM Cascade Delete to Nested Fields

问题

主模型:

type Page struct {
    ID                  int                  `gorm:"primarykey" json:"id"`
    Title               string               `gorm:"unique;not null" json:"title"`
    LocalizedPageTitles []LocalizedPageTitle `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"localizedPageTitles"`
    Paragraphs          []Paragraph          `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"paragraphs"`
    CreatedAt           time.Time            `json:"-"`
    UpdatedAt           time.Time            `json:"-"`
    DeletedAt           gorm.DeletedAt       `gorm:"index" json:"-"`
}
第一个子模型:
type Paragraph struct {
    ID                  uint                 `gorm:"primarykey" json:"id"`
    Text                string               `gorm:"unique;not null" json:"text"`
    PageID              uint                 `json:"pageId"`
    LocalizedParagraphs []LocalizedParagraph `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"localizedParagraphs"`
    CreatedAt           time.Time            `json:"-"`
    UpdatedAt           time.Time            `json:"-"`
    DeletedAt           gorm.DeletedAt       `gorm:"index" json:"-"`
}
第二个子模型:
type LocalizedParagraph struct {
    Localized
    ID          uint           `gorm:"primarykey" json:"id"`
    ParagraphID uint           `json:"paragraphId"`
    CreatedAt   time.Time      `json:"-"`
    UpdatedAt   time.Time      `json:"-"`
    DeletedAt   gorm.DeletedAt `gorm:"index" json:"-"`
}

这是我删除页面实体的方式:

func (p PageRepositoryImpl) Delete(id int) error {
    return p.db.Unscoped().Select(clause.Associations).Delete(&entity.Page{ID: id}).Error
}

上述函数会删除PageParagraphs,但如何自动删除LocalizedParagraphs

顺便说一下,我正在使用Sqlite。

dbmanager.go

func InitSQLite(filePath string) *gorm.DB {
    database, err := gorm.Open(sqlite.Open(filePath), &gorm.Config{})
    if err != nil {
        fmt.Printf("Error:%v", err)
        panic("Failed to connect database")
    }
    autoMigrateDB(database)
    return database
}

func autoMigrateDB(db *gorm.DB) {
    db.AutoMigrate(
        &entity.Page{},
        &entity.Paragraph{},
        &entity.LocalizedPageTitle{},
        &entity.LocalizedParagraph{},
    )
}
英文:

<h4>Main Model:</h4>

 type Page struct {
    	ID                  int                  `gorm:&quot;primarykey&quot; json:&quot;id&quot;`
    	Title               string               `gorm:&quot;unique;not null&quot; json:&quot;title&quot;`
    	LocalizedPageTitles []LocalizedPageTitle `gorm:&quot;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;&quot; json:&quot;localizedPageTitles&quot;`
    	Paragraphs          []Paragraph          `gorm:&quot;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;&quot; json:&quot;paragraphs&quot;`
    	CreatedAt           time.Time            `json:&quot;-&quot;`
    	UpdatedAt           time.Time            `json:&quot;-&quot;`
    	DeletedAt           gorm.DeletedAt       `gorm:&quot;index&quot; json:&quot;-&quot;`
    }

<h5>First Child:</h5>

type Paragraph struct {
	ID                  uint                 `gorm:&quot;primarykey&quot; json:&quot;id&quot;`
	Text                string               `gorm:&quot;unique;not null&quot; json:&quot;text&quot;`
	PageID              uint                 `json:&quot;pageId&quot;`
	LocalizedParagraphs []LocalizedParagraph `gorm:&quot;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;&quot; json:&quot;localizedParagraphs&quot;`
	CreatedAt           time.Time            `json:&quot;-&quot;`
	UpdatedAt           time.Time            `json:&quot;-&quot;`
	DeletedAt           gorm.DeletedAt       `gorm:&quot;index&quot; json:&quot;-&quot;`
}

<h5>Second Child:</h5>

type LocalizedParagraph struct {
	Localized
	ID          uint           `gorm:&quot;primarykey&quot; json:&quot;id&quot;`
	ParagraphID uint           `json:&quot;paragraphId&quot;`
	CreatedAt   time.Time      `json:&quot;-&quot;`
	UpdatedAt   time.Time      `json:&quot;-&quot;`
	DeletedAt   gorm.DeletedAt `gorm:&quot;index&quot; json:&quot;-&quot;`
}

This is how I delete my page entity:

func (p PageRepositoryImpl) Delete(id int) error {
	return p.db.Unscoped().Select(clause.Associations).Delete(&amp;entity.Page{ID: id}).Error
}

Above function deletes Page and Paragraphs but how can I remove LocalizedParagraphs automatically?

By the way I'm using Sqlite.

dbmanager.go

func InitSQLite(filePath string) *gorm.DB {
	database, err := gorm.Open(sqlite.Open(filePath), &amp;gorm.Config{})
	if err != nil {
		fmt.Printf(&quot;Error:%v&quot;, err)
		panic(&quot;Failed to connect database&quot;)
	}
	autoMigrateDB(database)
	return database
}

func autoMigrateDB(db *gorm.DB) {
	db.AutoMigrate(
		&amp;entity.Page{},
		&amp;entity.Paragraph{},
		&amp;entity.LocalizedPageTitle{},
		&amp;entity.LocalizedParagraph{},
	)
}

答案1

得分: 2

我无法执行此操作,没有使用delete hooksSelect(clause.Associations)语句已经处理了一级关联:

func (p PageRepositoryImpl) Delete(id int) error {
    return p.db.Unscoped().Select(clause.Associations).Delete(&entity.Page{ID: id}).Error
}

对于嵌套关联,我使用了删除钩子,以下是我的解决方案:

func (page *Page) BeforeDelete(tx *gorm.DB) error {
    paragraphs := make([]Paragraph, 0)
    err := tx.Where("page_id = ?", page.ID).Find(&paragraphs).Error
    if err != nil {
        return err
    }
    ids := make([]int, 0, len(paragraphs))
    for _, element := range paragraphs {
        ids = append(ids, int(element.ID))
    }
    lps := make([]LocalizedParagraph, 0)
    err = tx.Where("paragraph_id IN ?", ids).Unscoped().Delete(&lps).Error
    return err
}
英文:

I couldn't perform this action without delete hooks.
Select(clause.Associations) statement already take care of the one level associations:

func (p PageRepositoryImpl) Delete(id int) error {
	return p.db.Unscoped().Select(clause.Associations).Delete(&amp;entity.Page{ID: id}).Error
}

For nested associations, I used delete hook,
here is my solution:

func (page *Page) BeforeDelete(tx *gorm.DB) error {
	paragraphs := make([]Paragraph, 0)
	err := tx.Where(&quot;page_id = ?&quot;, page.ID).Find(&amp;paragraphs).Error
	if err != nil{
		return err
	}
	ids := make([]int, 0, len(paragraphs))
	for _, element := range paragraphs{
		ids = append(ids, int(element.ID))
	}
	lps := make([]LocalizedParagraph,0)
	err = tx.Where(&quot;paragraph_id IN ?&quot;, ids).Unscoped().Delete(&amp;lps).Error
	return err;
    }

huangapple
  • 本文由 发表于 2022年1月24日 20:05:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/70833600.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定