GOのORM sqlboiler 使ってみた　

この記事は[Go2 Advent Calendar 2017の3日目](https://qiita.com/advent-calendar/2017/go2)の記事です。

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

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

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

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

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

### sqlboilerとgooseをインストール
```bash	
# sqlboiler
$ go get -u -t github.com/volatiletech/sqlboiler

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

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

### dbconf.ymlに下記を追加
今回はpostgresを使用します
使用するDBのDBUSERNAMEとDBNAMEとDBPASSWORDをそれぞれ入力してください

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

### goose createコマンド実行
テーブル作成するためsqlファイルを生成

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

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

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

```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が出ればテーブルが作成される

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

### sqlboiler.tomlを作成

```bash	
$ touch sqlboiler.toml
```

### sqlboiler.tomlに下記を追加
```toml
[postgres]
  dbname="DBNAME"
  host="localhost"
  port=5432
  user="DBUSERNAME"
  pass="DBPASSWORD"
  sslmode="disable"
```

### sqlboilerコマンドを実行
実行完了後, modelsディレクトリが作成される

```bash
$ 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テーブルの全情報を取得するサンプル

```go
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
```go
// gorm
var user User
db.Find(&user)

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

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

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

### Preload
```go
// 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


## リンク
- [sqlboiler - github](https://github.com/volatiletech/sqlboiler)
- [goose - bitbucket](https://bitbucket.org/liamstask/goose/)