gpt4 book ai didi

go - 如何用 GORM (Go) 处理级联操作

转载 作者:IT王子 更新时间:2023-10-29 01:39:13 24 4
gpt4 key购买 nike

我正在测试 Go 的 GORM 库。我发现这个库特别有用,而且我一步一步地玩弄越来越复杂的概念。

我面临着级联运营管理的问题。

在某些问题上,创建者建议使用AfterDelete。问题是:在 After/BeforeDelete 函数中,嵌套项不存在。

大家有好的实现方法吗?

这是我的代码(如果有人发现 Gorm,几乎可以工作):

package main

import (
"time"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"fmt"
"github.com/satori/go.uuid"
)

type Company struct {
ID string `gorm:"primary_key;column:ID"`
Name string `sql:"size:255;unique;index" gorm:"column:Name"`
Employees []Employee // one-to-many relationship
Address Address // one-to-one relationship
}

func (u Company) TableName() string {
return "Company"
}
func (u Company) String() string {
return fmt.Sprintf("ID: %s | Name: %s | Employees: %v | Address: %v ", u.ID, u.Name, u.Employees, u.Address)
}
func (u *Company) BeforeCreate(scope *gorm.Scope) error {
scope.SetColumn("ID", uuid.NewV4().String())
return nil
}
func (u *Company) BeforeDelete(scope *gorm.Scope) error {
fmt.Println("BeforeDelete")
fmt.Println(u)
return nil
}
func (u *Company) AfterDelete(scope *gorm.Scope) error {
fmt.Println("AfterDelete")
fmt.Println(u)
return nil
}

type Employee struct {
ID string `gorm:"primary_key;column:ID"`
FirstName string `gorm:"column:FirstName"`
LastName string `gorm:"column:LastName"`
SocialSecurityNo string `gorm:"column:SocialSecurityNo"`
DateOfBirth time.Time `sql:"DEFAULT:current_timestamp" gorm:"column:DateOfBirth"`
Deleted bool `sql:"DEFAULT:false" gorm:"column:Deleted"`
CompanyID string `gorm:"column:Company_ID"`
Roles []Role // one-to-many relationship
}
func (u Employee) TableName() string {
return "Employee"
}
func (u Employee) String() string {
return fmt.Sprintf("ID: %s | FirstName: %s | Roles: %v ", u.ID, u.FirstName, u.Roles)
}
func (u *Employee) BeforeCreate(scope *gorm.Scope) error {
scope.SetColumn("ID", uuid.NewV4().String())
return nil
}

type Role struct {
Name string `gorm:"column:Name"`
Code string `gorm:"column:Code"`
EmployeeID string `gorm:"column:Employee_ID"`
}
func (u Role) TableName() string {
return "Role"
}
func (u Role) String() string {
return fmt.Sprintf("Name: %s | Code: %s", u.Name, u.Code)
}

type Address struct {
Country string `gorm:"column:Country"`
City string `gorm:"column:City"`
PostCode string `gorm:"column:PostCode"`
Line1 string `gorm:"column:Line1"`
Line2 string `gorm:"column:Line2"`
CompanyID string `gorm:"column:Company_ID"`
}
func (u Address) TableName() string {
return "Address"
}

func main() {
db := getDBConnection()
//If needed, you can create the file and schemas with the line below
createTables(db)
testCRUD(db)
}

func getDBConnection() (db *gorm.DB) {
//Change the file location for your needs
db, err := gorm.Open("sqlite3", `C:\Users\jbricout\Desktop\TestORM.db`)
if err != nil {
panic(err)
}

// Ping function checks the database connectivity
err = db.DB().Ping()
if err != nil {
panic(err)
}

return db
}

func createTables(db *gorm.DB) {
if err := db.CreateTable(&Company{}).Error; err != nil {
checkErr(err)
}
if err := db.CreateTable(&Address{}).Error; err != nil {
checkErr(err)
}
if err := db.CreateTable(&Employee{}).Error; err != nil {
checkErr(err)
}
if err := db.CreateTable(&Role{}).Error; err != nil {
checkErr(err)
}
}

func testCRUD(db *gorm.DB) {
sampleCompany := getInitializedCompany()

fmt.Println("Insert...")
if err := db.Create(&sampleCompany).Error; err != nil {
checkErr(err)
}
fmt.Println("Insert done with id : ", sampleCompany.ID)

fmt.Println("Find Only Company (Lazy load)...")
var firstComp Company
if err := db.Where("ID = ?", sampleCompany.ID).First(&firstComp).Error; err != nil {
checkErr(err)
}
fmt.Println("Company : ", firstComp)
fmt.Println("Find done")

fmt.Println("Find Only Company (Eager load)...")
var fullComp Company

db.Preload("Employees.Roles").Preload("Address").First(&fullComp)
if err := db.Where("ID = ?", sampleCompany.ID).First(&fullComp).Error; err != nil {
checkErr(err)
}
fmt.Println("Company : ", fullComp)
fmt.Println("Find done")

fmt.Println("Update...")
firstComp.Name = "Google Plus"
if len(firstComp.Address.Country) > 0 {
firstComp.Address.Country = "France"
}

if err := db.Save(&firstComp).Error; err != nil {
checkErr(err)
}
fmt.Println("Update done")

transaction := db.Begin()
fmt.Println("Delete...")
if err := transaction.Delete(&firstComp).Error; err != nil {
checkErrTransaction(err, transaction)
}

transaction.Commit()
fmt.Println("Delete done")
}

func getInitializedCompany() Company {
return Company{
Name: "Google",
Address: Address{
Country: "USA",
City: "Moutain View",
PostCode: "1600",
Line1: "Cloverfield Lane, 32",
Line2: "Apt 64",
},
Employees: []Employee{
Employee{
FirstName: "John",
LastName: "Doe",
SocialSecurityNo: "00-000-0000",
Roles: []Role{
Role{
Name: "Metier 1",
Code: "MET1",
},
Role{
Name: "Metier 2",
Code: "MET2",
},
},
},
Employee{
FirstName: "James",
LastName: "Dean",
SocialSecurityNo: "00-000-0001",
Roles: []Role{
Role{
Name: "Metier 1",
Code: "MET1",
},
},
},
Employee{
FirstName: "Joan",
LastName: "Dutsch",
SocialSecurityNo: "00-000-0002",
Roles: []Role{
Role{
Name: "Metier 2",
Code: "MET3",
},
},
},
},
}
}

func checkErr(err error) {
if err != nil {
panic(err)
}
}

func checkErrTransaction(err error, transaction *gorm.DB) {
transaction.Rollback()
if err != nil {
panic(err)
}
}

谢谢

最佳答案

要执行级联排除,必须在表之间添加外键。

这是我使用的示例,其中任务历史记录链接到任务。当我删除任务时,它已经删除了历史记录。

添加外键

// Add foreign key
// 1st param : foreignkey field
// 2nd param : destination table(id)
// 3rd param : ONDELETE
// 4th param : ONUPDATE
db.Model(&User{}).AddForeignKey("city_id", "cities(id)", "RESTRICT", "RESTRICT")

我的例子:

db.Model(&models.TaskHistoric{}).AddForeignKey("task_uuid", "tasks(uuid)", "CASCADE", "CASCADE")

关于go - 如何用 GORM (Go) 处理级联操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36456019/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com