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 についてはこちらを
ユーザ情報、スキル情報を取得する時に、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
使い所によっては、実装がスッキリしそうです。