LoginSignup
3
2

More than 3 years have passed since last update.

GORMでの主要メソッドによるゼロ値の取り扱いについて

Last updated at Posted at 2020-09-08

前提

gorm v2.0 で確認しています。

"gorm.io/gorm"

User 構造体は以下のものを使用しています。

type User struct {
    ID        int       `gorm:"column:id;primary_key:yes"`
    Email     string    `gorm:"column:email"`
    Age       int       `gorm:"column:age"`
    IsAdmin   bool      `gorm:"column:is_admin"`
    CreatedAt time.Time `gorm:"column:created_at"`
    UpdatedAt time.Time `gorm:"column:updated_at"`
}

Where

構造体を利用した書き方ですとフィールドがポインタ型でない場合ゼロ値("", 0, false)は検索できないため、事故を防ぐならベタで書くのが一番安全かと思います。

ただ、DB の構造体のフィールドをすべてポインタ型で宣言するようなルールになっている場合は構造体を利用した書き方で統一しても良いかと思います。

db.Where(User{Email: "example", Age: 10, IsAdmin: true}).Find(&user)
// => SELECT * FROM `users` WHERE `users`.`email` = "example" AND `users`.`age` = 10 AND `users`.`is_admin` = true;

db.Where(User{Email: "", Age: 0, IsAdmin: false}).Find(&user)
// => SELECT * FROM `users`;

db.Debug().Where("email = ?", "").Where("age = ?", 0).Where("is_admin", false).Find(&user)
// => SELECT * FROM `users` WHERE email = "" AND age = 0 AND `is_admin` = false;

Update

v1 では Where 句と同様に更新するフィールドがポインタ型でない場合はゼロ値の更新はできませんでした。

db.Where("id = ?", 1).Updates(User{Email: "", Age: 0, IsAdmin: false})
// => UPDATE `users` SET `updated_at`="2020-09-08 17:26:26.386" WHERE id = 1;
db.Where("id = ?", 1).Updates(User{Email: "example", Age: 10, IsAdmin: true})
// => UPDATE `users` SET `email`="example",`age`=10,`is_admin`=true,`updated_at`="2020-09-08 17:25:07.501" WHERE id = 1;

しかし、v2 で更新するカラムを明示的に選択した状態だとゼロ値でも更新することが出来るようになりました。

db.Select("is_admin").Where("id = ?", 1).Updates(User{Email: "", Age: 0, IsAdmin: false})
// => UPDATE `users` SET `is_admin`=false WHERE id = 1;

Save

save はゼロ値に関わらず構造体に設定してる値を INSERT・UPDATE します

db.Debug().Save(&user)
// => INSERT INTO `users` (`email`,`age`,`is_admin`,`created_at`,`updated_at`) VALUES ("",0,false,"2020-09-08 08:01:09","2020-09-08 13:34:23");
// => UPDATE `users` SET `email`="",`age`=0,`is_admin`=false,`created_at`="2020-09-08 08:01:09",`updated_at`="2020-09-08 22:34:22.664" WHERE `id` = 1;

Delete

delete は特にゼロ値は関係ありませんので割愛。

オマケ

v2からUpdateとDeleteに条件文が必須になりましたので、全件更新・削除の事故がなくなりました。
primary_key:yesつけ忘れて全件削除事故が起きた後にO/Rの仕様をしって驚愕したのはいい思い出です。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2