[Note] GORM 使用範例
TL;DR
- query @ gorm
- method chaining @ form
db.
Table("table_name"). // Model(&model{})
Select("select syntax").
Group("field_names").
Order("field_name").
Find(&model{}) // Rows()
- methods 可以分成 chain methods、finisher methods、new session method。
一對多(has many, belongs to)
情境
一個 User 有多個 Product,而一個 Product 只屬於一個 User。
Model 定義
User has many products
hasMany.go @ gist
- 使用
Products []Product
表示 User 有很多 Product - 如果沒有 Products 不希望顯示空陣列,可以在 json tag 中使用
omitempty
type User struct {
Name string `json:"name"`
Products []Product `json:"products"`
}
type Product struct {
Name string `json:"name"`
UserID uuid.UUID `json:"userId"`
User User `json:"user"`
}
Product belong to User
在 Product
model 需要
- 有
UserID
作為 foreign key(預設) - 有
User
Model 表示 belongs to,型別使用*User
搭配 json struct field tag 的omitempty
則可以在 Product 沒有 User 撈出資料時不要顯示此欄位
type Product struct {
Name string `json:"name"`
UserID uuid.UUID `json:"userId"`
User *User `json:"user,omitempty"`
}
CRUD 使用
Read: 使用 Preload 將 User 中關聯的 Product 取出
- 使用
db.Preload(clause.Associations)
可以一此把所有和 User 相關連的欄位(即,Product)一併撈出 - 使用
db.Preload("Products"
則可以指定要一併撈出的欄位名稱)
// database/user.go
func (d *GormDatabase) GetUserByID(userID uuid.UUID) (*model.User, error) {
user := &model.User{}
if err := d.DB.Preload(clause.Associations).Take(&user, userID).Error; err != nil {
return nil, err
}
return user, nil
}
取得的結果會像這樣:
{
"name": "aaron",
"products": [
{
"name": "Product 2",
"price": "200",
"sn": 2,
"comment": "Second Product",
"userId": "61ecf82b-8385-4606-83e9-70e13a4cdb5d"
},
{
"name": "Product 3",
"price": "300",
"sn": 3,
"comment": "Third Product",
"userId": "61ecf82b-8385-4606-83e9-70e13a4cdb5d"
}
]
}