GORMのCreate V2

GORMのCreate V2

こんにちは、Anti-Pattern Inc.の塚本です。

弊社では自社サービスの開発でGORMを使用しています。

V2の機能で関連するレコードも一度に登録できるようなので、試してみました。

例えば、この様なデータ構造です。ユーザはスキル情報を持っています

type userDTO struct {
 gorm.Model
 Name   string
 Email  *string
 Skills skillDTOs `gorm:"foreignKey:UserID"`
}

type skillDTO struct {
 gorm.Model
 UserID uint64
 Name   string
}

ユーザ情報、スキル情報を設定してCreateを実行します

user := userDTO{
 Name:   "testUser",
 Email:  func() *string { s := "test@test.com"; return &s }(),
 Skills: []skillDTO{
  {Name: "skill1"}, {Name: "skill2"}, {Name: "skill3"},
 },
}
r.db.Conn(ctx).Create(&user)

実行されたSQLログ

[rows:1] 
INSERT INTO "users"("created_at","updated_at","deleted_at","name","email")VALUES
('2021-10-04 01:18:54.177','2021-10-04 01:18:54.177',NULL,'testUser','test@test.com') RETURNING "id"

[rows:3] 
INSERT INTO "skills"("created_at","updated_at","deleted_at","user_id","name")VALUES
('2021-10-04 01:18:54.46','2021-10-04 01:18:54.46',NULL,919,'skill1'),
('2021-10-04 01:18:54.46','2021-10-04 01:18:54.46',NULL,919,'skill2'),
('2021-10-04 01:18:54.46','2021-10-04 01:18:54.46',NULL,919,'skill3')
ON CONFLICT("id") DO UPDATE SET "user_id" = "excluded"."user_id" RETURNING "id"

usersテーブル、skillsテーブルへのINSERT文が発行されてます。
また、usersに登録したレコードのid:919が、skillsのuser_idに指定されているのが分かります

ON CONFLICT("id") DO UPDATE SET についてはこちらを

https://www.postgresql.org/docs/11/sql-insert.html

ユーザ情報、スキル情報を取得する時に、Preloadを使っているのでその逆といった感じでしょうか

var find userDTO
result := r.db.Conn(ctx).Preload("Skills").Where("id = ?", 919).Find(&find)

実行されたSQLログ

[rows:1] 
SELECT * FROM "users" WHERE id = 719 AND "users"."deleted_at" IS NULL

[rows:3] 
SELECT * FROM "skills" WHERE "skills"."user_id" = 719 AND  "skills"."deleted_at" IS NULL

使い所によっては、実装がスッキリしそうです。