はじめに
Qiita初投稿です。
Go言語のORMツールであるGORMでマイグレーションとシーディングを実装したところ、何点か詰まったところがあったので、記事にしてみようと思いました。
GitHub
今回のソースコードはGitHub上にあるので、詳細はそちらを参考にしてください。
https://github.com/yasu2122yasu/article/tree/main/gorm-migration-seeding
前提条件
- M2 Macbook Air
- GoとDBのコンテナを使用
- Goのバージョンは1.18
- GoのフレームワークであるGinを利用(今回の実装はmain.goのみでも可能です)
- DBのイメージはMysql:8.0を使用
doceker-compose
version: '3.8'
services:
api:
container_name: api
build:
context: ./api
dockerfile: Dockerfile
tty: true
ports:
- 8080:8080
env_file:
- ./db/.env
depends_on:
- db
volumes:
- type: bind
source: ./api/
target: /go/src
db:
container_name: db
build:
context: ./db
dockerfile: Dockerfile
tty: true
platform: linux/x86_64
env_file:
- ./db/.env
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: test_database
MYSQL_USER: test_user
MYSQL_PASSWORD: password
ports:
- 3306:3306
volumes:
- ./db/initsql:/docker-entrypoint-initdb.d
volumes:
db-store:
Goを動かすapiコンテナとMySQLコンテナをdocker-composeにより立ち上げています。
initsqlディレクトリ配下にSQLファイルを置くことで、初期のDB/テーブル作成ができるのですが、自分の環境で実行するとデータベースを変更できなくなったので今回はアプリケーション側でmigrationとseedingを実行したいと思います。
volumes:
- ./db/initsql:/docker-entrypoint-initdb.d
Migraiton
Migraitonはデータベースに接続した後にすぐ実行するようにしています。
package database
import (
"api/model"
"fmt"
"os"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var Db *gorm.DB
func ConnectDatabase() {
dsn := fmt.Sprintf("%s:%s@tcp(db:3306)/%s?charset=utf8&parseTime=true", os.Getenv("MYSQL_USER"), os.Getenv("MYSQL_PASSWORD"), os.Getenv("MYSQL_DATABASE"))
var err error
Db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("Failed to connect to database")
}
Db.AutoMigrate(&model.User{})
UserSeed(Db)
}
以下の部分でマイグレーションを実行するmodelを指定しています。
Db.AutoMigrate(&model.User{})
今回使用するUserモデルは次のようになります。
package model
import (
"gorm.io/gorm"
)
type User struct {
gorm.Model
Name string
Email string
Password string
}
gorm.Modelには、ID、CreatedAt、UpdatedAt、DeletedAtがあらかじめ用意されているので、idなどの宣言は不要です。ただし、これらのフィールドが不要な場合は別途gormタグを利用するので、少し不便を感じるかもしれません。
Seeding
main.go実行時に、seedingも実行するため、usersテーブルのレコードをカウントして、レコードがあればseedingを実行しないようにしています。
package database
import (
"api/model"
"fmt"
"gorm.io/gorm"
)
func UserSeed(db *gorm.DB) error {
var count int64
// main.goが実行される度にレコードが生成されないようにする。
db.Model(&model.User{}).Count(&count)
if count > 0 {
return nil
}
users := model.User{Name: "Yamada Taro", Email: "mailmail@gmail.com", Password: "password"}
if err := db.Create(&users).Error; err != nil {
fmt.Printf("%+v", err)
}
return nil
}
実行
¥ docker-compose up -d
でコンテナを起動してください。
おわりに
今回はgormでマイグレーション・シーディングを実行してみました。
ただ現在会社で関わっているプロジェクトではentに興味があるので、entでのMigration・Seedingも実装してみたいなと思いました。
参考文献