GORMのPreloading (Eager loading)を使って2つのテーブルから値を取得する

#自己紹介
現在都内の企業でWebエンジニアのインターン生としてお世話になっている大学２年生です！
インターンや個人開発で学んだことや苦労したことを記事にしています！
よろしくお願いします🙇🏻‍♂️

#はじめに
インターンで2つのテーブルから値を取得するのに苦労したので、備忘録として記事に残しておきます！

#環境
- OS:M1MacOS ver12.0.1
- DB:Mysql ver8.0.27
- SQLマイグレーションツール:sql-migrate
- フレームワーク:Echo
- ORM:GORM

#Pleloading (Eager loading)とは
Preloadingとは事前読み込みのことです。
多くのORMで実装されている機能であり、GORMでも``Preload(モデル名)``を指定することで、リソースを先読みしてキャッシュできるようなる。

参考

https://qiita.com/tsubasaozawa/items/ac5a8a515fe4f7a139b0

公式サイトにはこう書いてあります。
>GORMの Preload を使用すると、別のSQLを発行して関連レコードを eager loading することができます。

参考
[GORM公式サイト](https://gorm.io/ja_JP/docs/preload.html)

#構造体の定義
GOの構造体は親テーブルに``foreignKey:XXXXX``で外部キーを設定します。
今回は``User_status_id``を外部キーとして設定するので``foreignKey:User_status_id``と記述します。
下記のように記述することでusersテーブルの``id``とuser_statuesテーブルの``user_status_id``が一致するデータを取得できます。
親テーブルはデフォルトで``id``が参照されるようになっています。

```go:user.go
type User struct {
	Id              int         `gorm:"primaryKey" json:"id"`
	First_name      string      `json:"first_name"`
	Family_name     string      `json:"family_name"`
	User_status_txt string      `json:"user_status_txt"`
	User_status     User_status `gorm:"foreignKey:User_status_id" json:"user_status"`
}

type User_status struct {
	Id             int        `gorm:"primaryKey" json:"id"`
	Status_name     string     `json:"status_name"`
	User_status_id int        `json:"user_status_id"`
}
```
親テーブルの参照されるデータを``id``から変更したい場合は
``AssociationForeignKey``を使うことで変更することができます。
下記は、``User_status_id ``→``Status_name ``、``AssociationForeignKey``に``User_status_txt ``を入れています。


```go:user.go
type User struct {
	Id              int         `gorm:"primaryKey" json:"id"`
	First_name      string      `json:"first_name"`
	Family_name     string      `json:"family_name"`
	User_status_txt string      `json:"user_status_txt"`
	User_status     User_status `gorm:"foreignKey:Status_name;AssociationForeignKey:User_status_txt" json:"user_status"`
}

type User_status struct {
	Id             int        `gorm:"primaryKey" json:"id"`
	Status_name     string     `json:"status_name"`
	User_status_id int        `json:"user_status_id"`
}
```


#値の取得
実際にPreloadを使い、値を取得してみます。
下記のように記述することでpreloadを使い2つのテーブルから値を取得する事ができます。

```go
func UserShow() echo.HandlerFunc {
	return func(c echo.Context) error {
		db := dbconnect.Connect()
		defer db.Close()	
		user := model.User{}
		user_id := c.Param("id")
		result := db.Preload("User_status").Find(&user, "id = ?", user_id)
		if result.RecordNotFound() {
			fmt.Println("レコードが見つかりません")
		}
		return c.JSON(http.StatusOK, user)
	}
}
```
###取得できるデータ
```json
{
    "id": 1,
    "first_name": "優介",
    "family_name": "飯嶋",
	"user_status_txt":"一般人",
    "user_status": {
        "id": 2,
        "status_name": "男性",
        "user_status_id": 1,
    } 
}
```

``id``と``user_status_id ``が一致しているデータが取れています。

また、``User_status_id ``→``Status_name ``、
``AssociationForeignKey``に``User_status_txt ``を入れた場合。

```json
{
    "id": 2,
    "first_name": "鈴木",
    "family_name": "太郎",
    "user_status_txt": "通行人A",
    "user_status": {
        "id": 3,
        "status_name": "通行人A",
        "user_status_id": 3,      
    }
}
```
``Status_name``と``User_status_txt ``が一致しているデータが取れています。

#終わりに
この記事が誰かの役に立てれば幸いです！

:::note warn
間違っている箇所もあるとは思いますが、教えてくださると助かります。
:::

ではいい一日を👍