#記事作成にあたり
GolangでORMを導入し、マイグレーション/CRUD処理を実施。GolangのORMはGORMやPrismaが有名だが、entを採用。entの説明や導入方法を記載。
#アジェンダ
- entとは
- 環境情報
- インストール
- スキーマ定義
- マイグレーション実行
#1. entとは
Facebook社(Meta)提供のGolangのORM。公式リファレンスや機能も充実。
#2. 環境情報
PC:Mac(CPUはintel製)
Go:1.17.6 ←Goのver大事。versionは1.16以降をインストールしてください。
開発エディタ:Visual Studio Code
#3. インストール
ディレクトリ作成
~/go/src $ mkdir ent_sample
~/go/src $ cd ent_sample
※GOPATH配下にディレクトリは作成ください。
go.modの作成
~/go/src/ent_sample $ go mod init
go: creating new go.mod: module ent_sample
entのインストール
~/go/src/ent_sample $ go get -d entgo.io/ent/cmd/ent
#4. スキーマ定義
テンプレート作成(Userテーブル)
~/go/src/ent_sample $ ent init User
※生成スキーマはアッパーキャメルでないとエラー出ます。
テンプレート作成後のディレクトリ構成
~/go/src/ent_sample $ tree
.
├── ent
│ ├── generate.go
│ └── schema
│ └── user.go
├── go.mod
└── go.sum
2 directories, 4 files
→generate.goと /schema/user.goが作成されている。中身を見ていきましょう。
generate.go
package ent
//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate ./schema
/schema/user.go
package schema
import "entgo.io/ent"
// User holds the schema definition for the User entity.
type User struct {
ent.Schema
}
// Fields of the User.
func (User) Fields() []ent.Field {
return nil
}
// Edges of the User.
func (User) Edges() []ent.Edge {
return nil
}
usersテーブルのスキーマ設定のため、Fields関数を変更。
/schema/user.go
package schema
import "entgo.io/ent"
// User holds the schema definition for the User entity.
type User struct {
ent.Schema
}
// Fields of the User. ←Fields関数を修正。
func (User) Fields() []ent.Field {
return []ent.Field{
field.Int("age").
Positive(),
field.String("name").
Default("unknown"),
}
}
// Edges of the User.
func (User) Edges() []ent.Edge {
return nil
}
ファイル生成
~/go/src/ent_sample $ go generate ./ent
ファイル生成後のディレクトリ構成
~/go/src/ent_sample $ tree
.
├── ent
│ ├── client.go
│ ├── config.go
│ ├── context.go
│ ├── ent.go
│ ├── enttest
│ │ └── enttest.go
│ ├── generate.go
│ ├── hook
│ │ └── hook.go
│ ├── migrate
│ │ ├── migrate.go
│ │ └── schema.go
│ ├── mutation.go
│ ├── predicate
│ │ └── predicate.go
│ ├── runtime
│ │ └── runtime.go
│ ├── runtime.go
│ ├── schema
│ │ └── user.go
│ ├── tx.go
│ ├── user
│ │ ├── user.go
│ │ └── where.go
│ ├── user.go
│ ├── user_create.go
│ ├── user_delete.go
│ ├── user_query.go
│ └── user_update.go
├── go.mod
└── go.sum
8 directories, 24 files
→ファイルが多数作成されていることが確認されますね。
#5. マイグレーション実行
dockerでPostgreSQLを準備。
docker-compose.yml
version: '3.1'
services:
postgres:
container_name: postgres
image: postgres:13
ports:
- 5432:5432
volumes:
- ./.data/postgres:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
PostgreSQLインスタンス生成
~/go/src/ent-test $ docker-compose up -d
Creating network "ent-test_default" with the default driver
Creating postgres ... done
追加ライブラリインストールの上、main.goを作成
ライブラリの追加インストール(postgressのドライバー)
go get github.com/lib/pq
main.go
package main
import (
"context"
"ent_sample/ent"
"ent_sample/ent/migrate"
"log"
_ "github.com/lib/pq" //postgresは必須。https://github.com/bmizerany/pq.go/issues/15
)
func main() {
client, err := ent.Open("postgres", "postgres://postgres:postgres@localhost:5432/enttest?sslmode=disable") // sslmodeが必要。https://stackoverflow.com/questions/21959148/ssl-is-not-enabled-on-the-server
if err != nil {
log.Fatalf("failed connecting to postgres: %v", err)
}
defer client.Close()
ctx := context.Background()
// マイグレーションの実行
err = client.Schema.Create(
ctx,
migrate.WithDropIndex(true),
migrate.WithDropColumn(true),
)
if err != nil {
log.Fatalf("failed creating schema resources: %v", err)
}
}
DBスキーマ作成
~/go/src/ent_sample $ psql -h localhost -p 5432 -U postgres
Password for user postgres:
psql (14.1, server 13.4 (Debian 13.4-1.pgdg100+1))
Type "help" for help.
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+------------+------------+-----------------------
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
(3 rows)
postgres=# create database ent_sample;
CREATE DATABASE
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
------------+----------+----------+------------+------------+-----------------------
ent_sample | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)
main.goの実行
~/go/src/ent_sample $ go run main.go
~/go/src/ent_sample $
環境確認
~/go/src/ent_sample $ psql -h localhost -p 5432 -U postgres
Password for user postgres:
psql (14.1, server 13.4 (Debian 13.4-1.pgdg100+1))
Type "help" for help.
postgres=# \c ent_sample
psql (14.1, server 13.4 (Debian 13.4-1.pgdg100+1))
You are now connected to database "ent_sample" as user "postgres".
ent_sample=# \dt
List of relations
Schema | Name | Type | Owner
--------+-------+-------+----------
public | users | table | postgres
(1 row)
ent_sample=# \d users
Table "public.users"
Column | Type | Collation | Nullable | Default
--------+-------------------+-----------+----------+----------------------------------
id | bigint | | not null | generated by default as identity
age | bigint | | not null |
name | character varying | | not null | 'unknown'::character varying
Indexes:
"users_pkey" PRIMARY KEY, btree (id)
#参考文献
https://entgo.io/