SYM's Tech Knowledge Index & Creation Records

「INPUT:OUTPUT=1:1以上」を掲げ構築する Tech Knowledge Stack and Index. by SYM@設計者足るため孤軍奮闘する IT Engineer.

Golang Gorm 実践メモ&注意点

Golang Gorm 実践メモ&注意点

随時追記

公式ドキュメントhttps://gorm.io/ja_JP/docs/index.html

注意事項

  1. Create、Update、Save の振舞いの違い

  2. Create: 新規作成

  3. Update: 空値が除外、任意のカラムのみ選択可能
  4. Save: 空値も含めて全てのカラムを一律保存

使い分けの方針

  • 新規レコード作成時: Create
  • 既存レコード更新時: Update
  • 更新時に空値を含めてStructで更新: Save
  • 更新時に空値を含めてMapで更新: Update

Saveは、なければ新規作成、あれば更新。となるため注意が必要

  1. (コールバックで)自動的に関連レコードが全て保存される

関連レコード含めて全て更新される

回避: 関連レコードの一括保存や、そのほかBeforeCreateのようなコールバックメソッドを呼ばずに更新したい場合、 UpdateColumn、UpdateColumnsを使用

  1. マイグレーション機能は本番向きでない

一回きりのマイグレーションで完結する場合は十分かもしれないが、長期的な運用の管理には機能不足

migrate 等、別のツールを使う

  1. Query Conditions関数は、必ずWhere() を使用して条件を指定
db.Where("id = ?", 1).Find(&users)

様々な書き方ができるように設計されているが

db.Where("id = ?", "1").Find(&users)
// SELECT * FROM `users`  WHERE (id = '1')
db.Where(User{ID: 1}).Find(&users)
// SELECT * FROM `users`  WHERE (`users`.`id` = 1)
db.Find(&users, "id = ?", "1")
// SELECT * FROM `users`  WHERE (id = '1')
db.Find(&users, User{ID: 1})
//  SELECT * FROM `users`  WHERE (`users`.`id` = 1)
db.Find(&users, "1")
// SELECT * FROM `users`  WHERE (`users`.`id` = '1') 

5番目の書き方トラップがあり、以下のように書くと任意のSQL実行できてしまう。

userInputID := "1=1"
db.Find(&users, userInputID)
// SELECT * FROM `users`  WHERE 1=1  ※全権取得になる

userInputID := "1=1);DROP table users;--"
db.Find(&users, userInputID)
// SELECT * FROM `users`  WHERE (1=1);DROP table users;--)  ※usersテーブル削除

ref