4
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?

GOのORM GORM + genを使ってみる

4
Last updated at Posted at 2025-12-22

GOのORMであるgormと、gormの一機能であるgenを使い、DBからデータを取得してみます。
genはテーブル定義から構造体等を自動生成してくれるGORMの機能です。
Gen公式:https://gorm.io/gen/index.html

環境設定

Ubuntuでgorm-sampleを作成して、その中でやっていきます。

$ mkdir gorm-sample
$ cd gorm-sample

localにGOを導入して即席でパスを通します。

$ wget https://go.dev/dl/go1.24.0.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.24.0.linux-amd64.tar.gz
$ echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
$ source ~/.bashrc

$ go version
go version go1.24.0 linux/amd64

※aptでインストールするとバージョンが古く、gorm/genの導入時に怒られることがあるので上記のようにしています。

go: golang.org/x/tools@v0.40.0 requires go >= 1.24.0 (running go 1.22.2)

GORMを入れます。

$ go get gorm.io/gorm
$ go get gorm.io/driver/mysql

genも入れます。

$ go get -u gorm.io/gen

動作を確認するために、localDBにusersテーブルを作成します。

mysql> CREATE TABLE users (
    ->   id   BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    ->   name VARCHAR(255) NOT NULL
    -> );
Query OK, 0 rows affected (0.07 sec)

データも投入しておきます。(insert文省略)

mysql> select * from users;
+----+--------+
| id | name   |
+----+--------+
|  1 | tarou  |
|  2 | hanako |
+----+--------+
2 rows in set (0.00 sec)

genで生成する

gorm-sample/gen/gen.goを作成します。

package main

import (
	"gorm.io/driver/mysql"
	"gorm.io/gen"
	"gorm.io/gorm"
)

func main() {
	dsn := "test:testpass@tcp(127.0.0.1:3306)/sample?charset=utf8mb4&parseTime=True&loc=Local"

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)
	}

	g := gen.NewGenerator(gen.Config{
		OutPath:      "./query",
		ModelPkgPath: "./model",
		Mode:         gen.WithDefaultQuery,
	})

	g.UseDB(db)
	models := g.GenerateAllTable()
	g.ApplyBasic(models...)	
	g.Execute()
}

genを利用してmodel、queryを生成します。

xxx:~/gorm-sample$ go run gen/gen.go
2025/12/20 21:57:33 find 1 table from db: [users]
2025/12/20 21:57:33 got 2 columns from table <users>
2025/12/20 21:57:33 Start generating code.
2025/12/20 21:57:33 generate model file(table <users> -> {model.User}): /home/xxx/gorm-sample/model/users.gen.go
2025/12/20 21:57:33 generate query file: /home/xxx/gorm-sample/query/users.gen.go
2025/12/20 21:57:33 generate query file: /home/xxx/gorm-sample/query/gen.go
2025/12/20 21:57:33 Generate code done.

あっという間に生成されました。
image.png
image.png

動作確認

簡単なWhere句で絞って、レコードを取得してみます。
gorm-sample/main.goを作成します。

package main

import (
	"context"
	"fmt"
	"log"

	"example.com/gorm-sample/db"
	"example.com/gorm-sample/query"
)

func main() {
	fmt.Println("== raw SQL ==")

	sqlDB := db.ConnectSQL()
	defer sqlDB.Close()

	rows, err := sqlDB.Query(
    "SELECT id, name FROM users WHERE name = ?",
    "hanako",
  )
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var id uint64
		var name string
		rows.Scan(&id, &name)
		fmt.Printf("id=%d name=%s\n", id, name)
	}

	fmt.Println("\n== gorm/gen ==")

	gormDB := db.ConnectGorm()
	q := query.Use(gormDB)
	ctx := context.Background()

	users, err := q.User.WithContext(ctx).Where(q.User.Name.Eq("hanako")).Find()
	if err != nil {
		log.Fatal(err)
	}

	for _, u := range users {
		fmt.Printf("id=%d name=%s\n", u.ID, u.Name)
	}
}

動作確認した結果、レコードを取得できました。

xxx:~/gorm-sample$ go run main.go
== raw SQL ==
id=2 name=hanako

== gorm/gen ==
id=2 name=hanako

感想

・テーブル定義が揺れるシーンで強そう
テーブルに変更が入っても構造体を簡単に修正できます。当然コンパイルエラーになりますので、型やカラム名の修正を取りこぼすことが大きく減りそうです。
開発初期段階や、大人数があちこち触るリプレイスのようなシーンで事故を減らせそうに見えます。
ただし独自の記法があるので、人によっては記述に時間がかかってしまうかもしれません。

・規模が大きくなると扱いが難しそう
ビジネスの規模拡大で複雑なSQLが必要になったとき、結局生SQLに頼らざるを得ないシーンが出てきそうに思います。
また、N+1問題のためにPreload()を使用するなど、パフォーマンス面での問題を解決するのにGORMの知識が必要になっていくようです。

GORM/genだけで最初から最後まで、何から何までというのは難しそうに感じました。

おまけ

local mysqlは以下の手順で準備しています。

WSL2 + Docker ComposeでローカルMySQL環境を構築する

4
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
4
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?