[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。
與 Database 連線
- Connecting to a Database @ gorm
除了下述說明外,建議可以參考 go-snippets/pkg/gorm:
import (
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
func initDatabase(dsn string) (*database.GormDatabase, error) {
db, err := database.New(dsn, &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
return nil, err
}
if err := db.AutoMigrate(new(model.Organization)); err != nil {
log.Fatal(err.Error())
}
fmt.Println("Database connected ...")
return db, nil
}
func main() {
dsn := "sslmode=disable host=localhost port=5432 user=postgres dbname=gorm_sandbox"
db, err := initDatabase(dsn)
}
CRUD Interface
template/database/product @ go-snippets
Update
Update @ gorm
db.Update()
在 Update 中可以透過 struct
或 map
一次更新多個欄位,但要特別留意的是
- 使用 struct 的方式只會更新 non-zero value,也就是說如果值是
false
或0
這類的都不會被保存 - 使用
map
的方式才會更新 zero-value,因此個人會建議使用 map 的方式來避免可能的 bug
// Update attributes with `struct`, will only update non-zero fields
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
// Update attributes with `map`
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
💡 會建議使用 map 的方式(而非 struct)來進行更新避免可能的 bug
db.Save()
使用 db.Save()
時,沒給的值會全部被清空(包括 createdAt
、除了 updatedAt
),所以如果要用 save,一定要把舊有的資料先拉出來,對要改變的內容進行修改後,在呼叫 save
:
// https://gorm.io/docs/update.html
// 先把原有資料拉出來
db.First(&user)
// 修改要改動的欄位就好
user.Name = "jinzhu 2"
user.Age = 100
// 使用 Save
db.Save(&user)
⚠️ 使用
db.Save()
時所有的欄位都會更新,因此若沒給的話會導致該值變回 zero-value,記得一定要先把資料拉出來後,修改要改的資料後,在呼叫 Save。
Upsert
Upsert-On-Conflict @ Create > Upsert
- 使用 Gorm 內建的 upsert 方法會類似 Save,有指定更新欄位的一定要給值,否則會被清空
- 使用
Where
+ Assign + FirstOrCreate` 組出來的 upsert 方法會類似 update,需要留意當使用者想要清空原本的資料時,因為後端接收到的是 zero value,所以不會執行清空的動作