Open4
GoのORM sqllaの使い方
所属している会社内ではいくつかのプロジェクトで使われている自作のORM sqllaというものがあるが、これについて日本語でまとめた記事が最近ではないので、雑にまとめてみる。
ライブラリ自体はこちら
sqllaの特徴
- MySQLおよびsqlite向けの一部のSQLを扱うことが出来る
- structでテーブルスキーマを定義して、それをベースにクエリビルダーのコードを生成する
- クエリビルダーで生成したSQLの結果をテーブルスキーマstructに対してマッピングが行える
- DB接続の管理は行わない
sqllaでのスキーマ定義とコード生成
まず、以下のようなテーブルがあるとする。
ちなみにここからはMySQL前提で説明する。
CREATE TABLE `task` (
`id` BIGINT unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(191) NOT NULL,
`description` TEXT NOT NULL,
`status` INTEGER unsigned NOT NULL DEFAULT 1,
`created_at` DATETIME NOT NULL,
`updated_at` DATETIME NOT NULL
);
このスキーマをsqlla向けに書いたGoのstructにすると以下のようになる。
type Task struct {
ID uint64 `db:"id,primarykey"`
Name string `db:"name"`
Description string `db:"description"`
Status uint32 `db:"status"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
このstructを定義したpackageで以下のgo generateの定義を書く
//go:generate sqlla
go generateを行う前に、以下のコマンドでsqllaコマンドを使えるようにしておく
$ go install github.com/mackee/go-sqlla/v2/cmd/sqlla@v2.10.0
そして、go generateを行う
$ go generate
するとtaskテーブルを扱うためのクエリビルダーとマッピングメソッドが収まるコードが生成される。この場合はtask.gen.go
が生成されている。
生成されたコードを用いたSELECT
生成されたコードと同じパッケージで使う前提でSELECTを行うコードを書く。ここではmain packageに生成した前提で書いている。
package main
import (
"context"
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "user:password@/dbname")
if err != nil {
panic(err)
}
ctx := context.Background()
task, err := NewTaskSQL().Select().ID(1).SingleContext(ctx, db)
fmt.Printf("%#v\n", task)
}
完全な動作するコードを提示したが、ポイントとしては、
-
database/sql
をそのまま用いるときと同じように*sql.DB
を作る -
NewTaskSQL().Select()
でTaskテーブルに対するSELECT文を生成するクエリビルダーを作成 - クエリビルダーの
ID(1)
メソッドがWHERE id = 1
に相当する -
SingleContext
でクエリを実行し、返ってきた結果を前述したTask structへのマッピングを行って返す
となっている
ID
以外にもstructに定義したfieldで絞り込みを行うメソッドが生えている
task, err := NewTaskSQL().Select().
Name("foobar").
Description("Lorem Ipsum").
Status(1).
CreatedAt(time.Now()).
UpdatedAt(time.Now().Add(12*time.Hour)).
SingleContext(ctx, db)