1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Go】gormでテーブル名と構造体の名前が違う時のtips

Posted at

Go難しいです。gormは「なんでやねん」と思うことが多いです。
元Railsエンジニアには早すぎた技術なのかもしれません🥺

Many To Many周りの公式の記事が少しわかりにくくて、tipsを書いておきます

Many To Many (many2many)

gormではPreload()する際に、構造体のフィールドのタグ(reflect.StructTag)を仕込むことで、中間テーブルを簡単にORM側に理解させることができます。

普通の書き方

gorm内部的には、Fieldという構造体でTagSettings map[string]stringで値を持っていて、全部大文字に変換してるのでmap[MANY2MANY:many2many:user_languages]という感じで保存してあります

// usersテーブル
type User struct {
  ID        uint
  Languages []*Language `gorm:"many2many:user_languages;"`
}

// languagesテーブル
type Language struct {
  ID   uint
  Name string
}

// 中間テーブルの構造体を定義せずに、Eager Loadingが実行できる
DB.Model(&User{}).Preload("Languages")

テーブル名と構造体名が違う書き方

こういう書き方がGo的に良いか悪いかどうかは置いといて😅
Languageの構造体にフィールドを追加したくなくて、Languageと同じフィールドを持つLanguageWithOwnを作成した時の、many2manyの書き方で
foreignKey, joinForeignKey, References, joinReferencesの4つを設定する必要があります
前述の通り、大文字小文字は内部で吸収されているので関係ないです。

// usersテーブル
type User struct {
  ID        uint
  Languages []*OwnLanguage `gorm:"many2many:user_languages;foreignKey:id;joinForeignKey:user_id;References:id;joinReferences:language_id;"`
}
// foreignKey:id
// joinForeignKey:user_id
// References:id
// joinReferences:language_id

// languagesテーブル
type LanguageWithOwn struct {
  ID   uint
  Name string
  Own  bool // 母国語かどうか
}

// 構造体とテーブル名を一致させる
func (l *LanguageWithOwn) TableName() string {
	return "languages"
}

// Eager Loadingが実行され、User.Languagesに値が入る
DB.Model(&User{}).Preload("Languages")

あんまGoのライブラリのソース読まないけど、jsのライブラリとテイストは似てるなと思った(所感)

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?