この記事はGo2 Advent Calendar 2017の3日目の記事です。

良い機会だったので初投稿してみました。

普段ORMはgormを使用しているのだがsqlboilerはパフォーマンスがgormに比べてパフォーマンスがよいという話を聞いて実際に使ってみたのでまとめを記事にしました。

sqlboilerとは

データベーススキーマに合わせたGOのORMを生成ツールです。
gormとかとは違い、コードファーストではなくデータベースファーストのORMとなってます。

つまりどういうことかというと、データベーススキーマを先に作成しそこからgoのコードを生成してくれます。

準備編

今回Migrationツールのgooseを使用してデータベーススキーマを管理していきます。
依存解決ツールはdepを使います。(説明はしませんが)

sqlboilerとgooseをインストール

# sqlboiler
$ go get -u -t github.com/volatiletech/sqlboiler

# goose
$ go get bitbucket.org/liamstask/goose/cmd/goose

dbconf.ymlを追加する

# dbディレクトリを作成する
mkdir db
# dbconf.ymlをdbディレクトリに作成する
touch db/dbconf.yml

dbconf.ymlに下記を追加

今回はpostgresを使用します
使用するDBのDBUSERNAMEとDBNAMEとDBPASSWORDをそれぞれ入力してください

development:
    driver: postgres
    open: user=DBUSERNAME dbname=DBNAME pass=DBPASSWORD sslmode=disable  

goose createコマンド実行

テーブル作成するためsqlファイルを生成

$ goose create CreateUserTable sql
goose: created $GOPATH/src/path/to/db/migrations/20171202220708_CreateUserTable.sql

# db/migration/ ディレクトリに作成される

作成されたファイルにSQLを書く


-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied

-- put your sql
CREATE TABLE users (
    id integer primary key,
    name varchar(255),
    birthday date,
    age integer
);


-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back

-- put your sql
DROP TABLE IF EXISTS users;

goose up コマンド実行

プロジェクトディレクトリ直下にて実行する
OKが出ればテーブルが作成される

# $GOPATH/src/path/toにて
$ goose up
goose: migrating db environment 'development', current version: 0, target: 20171202220708
OK    20171202220708_CreateUserTable.sql

sqlboiler.tomlを作成

$ touch sqlboiler.toml

sqlboiler.tomlに下記を追加

[postgres]
  dbname="DBNAME"
  host="localhost"
  port=5432
  user="DBUSERNAME"
  pass="DBPASSWORD"
  sslmode="disable"

sqlboilerコマンドを実行

実行完了後, modelsディレクトリが作成される

$ sqlboiler -b goose_migrations postgres

# こんな感じのファイルが生成されます
models/
├── boil_main_test.go
├── boil_queries.go
├── boil_queries_test.go
├── boil_suites_test.go
├── boil_table_names.go
├── boil_types.go
├── goose_db_version.go
├── goose_db_version_test.go
├── main_test.go
├── users.go
└── users_test.go

コーディング

sampleコード

下記のコードはusersテーブルの全情報を取得するサンプル

package main

import (
    "database/sql"
    "log"

    "path/to/models"

    "github.com/k0kubun/pp"
    _ "github.com/lib/pq"
    "github.com/vattle/sqlboiler/boil"
)

func main() {
    db, err := sql.Open("postgres", "dbname=DBNAME user=DBUSERNAME sslmode=disable")
    if err != nil {
        log.Println(err)
        return
    }

    boil.SetDB(db)

    users, err := models.UsersG().All()
    if err != nil {
        log.Println(err)
        return
    }

    pp.Println(users)
}

gormの書き方とsqlboilerの書き方を比較

普段gorm使っているので比較を一部書いてみた
ざっくりした紹介になってしまうかもしれませんがm(_ _)m

Find

// gorm
var user User
db.Find(&user)

// sqlboiler
user, err := models.Users(db).One()

Update

// gorm
var user User
db.Model(&user).Update("name", "hello")

// sqlboiler
user, _ := models.Users(db).One()
user.Name = "update"
user.Update(db)

Preload

// gormの場合
var user User
db.Preload("Orders").Find(&user)

// sqlboiler
// "github.com/volatiletech/sqlboiler/queries/qm"このパッケージをimportする必要がある
user, err := models.Users(db, qm.Load("Orders")).One()

まとめ

データベーススキーマから設定するのでテーブル設計をしっかりしたうえでコーディングができそうだなって感じがした。
sqlboilerをまだあんまり触っていないが今のところgormよりはいいかなって感じがした。

おわりに

自分自身準備編でいろいろ詰まって、コードが少なくなってしまいました。申し訳ないですm(_ _)m

リンク