Je teste la librairie GORM de Go. Je trouve cette lib particulièrement utile et, petit à petit, je joue avec des notions de plus en plus compliquées.Comment traiter le fonctionnement en cascade avec GORM (Go)
Je suis confronté au problème de la gestion des opérations en cascade.
Sur certains problèmes, le créateur suggère d'utiliser AfterDelete. Le problème est: dans les fonctions After/BeforeDelete, les éléments imbriqués ne sont pas présents.
Est-ce que tout le monde a un bon moyen de mettre en œuvre cela?
Voici mon code (travail presque si quelqu'un découvre 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)
}
}
Merci