LoginSignup
8
2

More than 1 year has passed since last update.

GolangにORM導入(ent migration編)

Posted at

記事作成にあたり

GolangでORMを導入し、マイグレーション/CRUD処理を実施。GolangのORMはGORMやPrismaが有名だが、entを採用。entの説明や導入方法を記載。

アジェンダ

  1. entとは
  2. 環境情報
  3. インストール
  4. スキーマ定義
  5. マイグレーション実行

1. entとは

Facebook社(Meta)提供のGolangのORM。公式リファレンスや機能も充実。
スクリーンショット 2022-02-14 13.03.13.png

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)

参考文献

8
2
1

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