2016-04-06 6 views
1

私はGoのGORM libをテストしています。 私はこのライブラリが特に有用であることを見つけました。ステップバイステップで、私はますます複雑な考え方で遊んでいます。GORM(Go)でカスケード操作を処理する方法

私は操作管理のカスケード接続の問題に直面しています。

特定の問題では、作成者はAfterDeleteの使用を提案しています。 問題は、After/BeforeDelete関数では、ネストされた項目が存在しないことです。

誰もがこれを実装する良い方法はありますか?ここで

私のコード(誰かがゴームを発見された場合、ほとんどの作業)である:

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) 
    } 
} 

おかげ

答えて

0

私は私の問題への対応のために、このソリューションを実装している:すべてのために

func DeleteContentCascade(content *Content, db *gorm.DB, debug bool) error { 

    if debug { 
     db = db.Debug() 
    } 

    for _, child := range content.Children { 
     DeleteChildCascade(&child, db, debug) //Custom method like the current 
    } 

    if err := db.Delete(content).Error; err != nil { 
     return err 
    } 

    return nil 
} 

私のDB管理の "アイテム"ファイル、私はカスタム関数DeleteCascadeを作成しました。

私はカスケード除外を実行するために私の英語

申し訳ありません私の友人こんにちは、それは:)

0

を助けていただければ幸いです、あなたはテーブル間の外部キーを追加する必要があります。

これは、タスク履歴がタスクにリンクされる場所で使用された例です。タスクを削除すると、すでに履歴が削除されます。

追加外部キー

// 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") 
関連する問題