我正在测试 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)
}
}
谢谢