Ich prüfe Go's GORM lib. Ich finde diese Lib besonders nützlich und, Schritt für Schritt, spiele ich mit immer komplizierteren Vorstellungen.Wie behandeln Kaskadenbetrieb mit GORM (Go)
Ich bin mit dem Problem der Kaskadierung Operation Management konfrontiert.
Bei bestimmten Problemen schlägt der Verfasser vor, die AfterDelete zu verwenden. Das Problem ist: in den After/BeforeDelete-Funktionen sind verschachtelte Elemente nicht vorhanden.
Hat jeder eine gute Möglichkeit, dies zu implementieren?
Hier ist mein Code (fast arbeiten, wenn jemand Gorm entdeckt):
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)
}
}
Dank