2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

gormでMigration+Seedingを実行する

Posted at

はじめに

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

docker-compose.yml
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はデータベースに接続した後にすぐ実行するようにしています。

database.go
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モデルは次のようになります。

User.go
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を実行しないようにしています。

seeder.go
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

でコンテナを起動してください。

スクショになりますが、実行結果を貼っておきます。
 スクリーンショット 2023-12-10 23.42.02.png

おわりに

今回はgormでマイグレーション・シーディングを実行してみました。

ただ現在会社で関わっているプロジェクトではentに興味があるので、entでのMigration・Seedingも実装してみたいなと思いました。

参考文献

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?