[golang] SQLBoiler のいろは (1) 設定 ~ 基本 CRUD 実行まで

[golang] SQLBoiler のいろは (1) 設定 ~ 基本 CRUD 実行まで

こんにちは。七色眼鏡です。
前回の更新から時間が空いてしまいました。ちょっと今年から小さな案件の PM をやらせてもらえることになって、そっちに注力していたことが主な原因です。(主な。)

今回から数回は、golang の ORM ツールである SQLBoiler について調査・学習していきたいと思います。

SQLBoiler とは

SQLBoiler とは、既に存在するテーブル定義から自動で ORM を生成するツールです。

DDL さえあればそこから SQLBoiler が golang のファイルを自動生成してくれ、かつそこにテーブル struct やクエリ実行のための各種レシーバなどを用意してくれるため、ユーザーはそれを呼び出すだけでクエリを実行することができます。

golang の ORM ツールは数が少なくそもそも選択肢があまりないのですが、SQLBoiler はその中でも評価の高いツールです。

これからやること

ここから数記事をかけて、以下の内容に触れていきます。

・SQLBoiler を使うための準備について (本記事)
・SQLBoiler による model 生成の実践 (本記事)
・model を使用した基本的な query の発行 (本記事)
・model を使用した応用的な query の発行 (次記事)

環境準備

環境情報

以下のものを準備していきましょう。

・golang v 1.13.0
・SQLBoiler v 3.6.1
・MySQL v 8.0.19

golang の準備

今回は go.mod を使用しているので、go.1.12 (1.11 でも設定次第では ok ) 以上での操作を推奨します。golang の install 方法は割愛します。筆者は goenv で 1.13.0 にしています。

golang の準備ができたら、下記コマンドでテスト用ディレクトリを作成し、その直下にモジュールを作成しておきましょう。

以下、基本的にはこの sqlboiler_test/ 以下で作業を進めていきます。

SQLBoiler の準備

lib

go get コマンドでSQLBoiler を用意しましょう。使用するのは、SQLBoiler 本体と、mysql 用の driver です。

設定ファイルの作成 (sqlboiler.toml)

プロジェクトのルートに、SQLBoiler の設定ファイルを作成します。
この設定を元にSQLBoiler が DB に接続を行い、model を自動生成してくれるようになります。

今回の設定ファイルの内容は以下の通りです。

sqlboiler.toml

DB への接続情報ですね。
今回はミニマムな構成でテストしますが、より詳細な設定を行うこともできます。
詳しい内容については、公式の README を参照してください。

https://github.com/volatiletech/sqlboiler

MySQL の準備

DDL の準備

DDL は先に用意しておきましょう。以下の create 文を使用します。
基本的に制約はちゃんとかけていきます。
なお今回の記事では、User しか使いません。

・User : 他テーブルから参照される親テーブル。
・Division : 必ず User を親に持つ子テーブル。外部キー制約で User と紐づく。
・Branch : 任意で User を親に持つ子テーブル。制約はなく、user_id は nullable。

ddl.sql

MySQL 本体の準備

以下のコマンドで取得します。既に存在している人はスキップしてください。

加えて、mysql 用の driver も取得しておきましょう。

接続設定

設定周りに強い人は、ここも読み飛ばしてください。筆者は弱いので、備忘の意味でメモしていきます。

やることは、テスト用ユーザーの作成と、それに対する権限の付与です。
inline で解説していきます。

setting how2

テーブル作成

設定が終了したら、先ほど作成した DDL を実行し、テーブルを作成しましょう。

Model 生成

ここまでで環境設定が終了しています。次にSQLBoiler を使用して model を生成しましょう。
ルートディレクトリにて、以下のコマンドを実行します。

SQLBoiler の設定ファイルが正常で、DB 接続が確立し、 かつ DDL が適切に実行されていれば、ルートディレクトリに models というディレクトリが作成されているはずです。(models がデフォルトの出力位置です。これは toml で変更できます。)
models に下記ファイルが出力されていることを確認してください。

ここまで出来たら、準備は全て終了です。

基本 CRUD の実装

では実装に入っていきます。今回は全て main パッケージで作業をしていき、作成するファイルも全てルートディレクトリに展開してしまいます。

DB 接続の実装 (connection.go)

用意しているデータベースへのコネクションを形成するための実装です。
本題からはそれるので詳細説明は割愛します。

注意点としては、

_ “github.com/go-sql-driver/mysql”
をちゃんと import しないと動かない、ということくらいでしょうか。
なお今回は作成したコネクションをどこからでも使用できるように、グローバル変数を用いています。
connection.go

model struct の準備

SQLBoiler により models が生成されています。この models の中の テーブル struct を使用することで、各種 CRUD などを行うことが出来ます。

これは直接参照すれば良いので別途 struct を作成する必要はないのですが、あとで作成する struct が混在すると嫌なので、別に定義しておきます。

structs.go

なんのことはない、ただ既に存在する models.User を参照するだけの struct です。
これを使用しない場合は、以下 UserModel を使用している場所を適宜 models.User に書き換えて貰えば良いです。

Insert の実装

では Insert を実装します。と言っても難しいことは何もないです。
自動生成された models のテーブル struct に、テーブルの列名に相当する変数が既に用意されているのでそれを設定し、これまた既に用意されている Insert のメソッドを実行するだけです。

insert

models に用意されている Insert は次のように実装されています。

・ctx は今回は特に意識しないので、空のコンテキスト (context.Backgroud) を渡せば良いです。

・exec には先に作成している DB コネクションを渡します。グローバル変数にしていたので、どこかで init さえ走らせておけばこれで動きます。

・columns には、使用する列の情報を指定します。boil.Infer() を使用すると、全ての列情報を使用します。特定の列を使用する場合には boil.Whitelist, 特定の列を使用しない場合には boil.Blacklist などを使用します。

上記の関数を実行した後に DB を覗いてみると、下記のように正常に動作したことを確認できます。

 

Update の実装

次は Update です。Update は Insert とほとんど違いがありません。
全体的にSQLBoiler は、基本 CRUD の実行は本当に簡単です。

Update

 

引数も、Insert の時と同じですね。

注意点としては、models で提供される Update は PK での指定しか受け付けないということです。つまり今回は User の PK である user_id を必ず指定しなければいけません。

PK を使用できない (PK 以外の複数列での絞込みが行われる対象への更新処理が必要) は、この Update では無く、他の方法で更新処理を行うことになります。その方法については、次回の記事で触れていきたいと思います。

実行結果は次の通りです。

Select の実装

Select は Insert / Update とはちょっと毛色が違います。と言っても簡単なことには変わりないですけれども。

先に実装を見てみましょう。

Select

Insert / Update が User struct に生えているレシーバだったのに対して、ここで使用している FindUser は、PK を渡されて実行される普通の関数です。

ので、models.User を 参照したり new したりする必要は、Select の場合には必要ありません。

引数の最後では選択する列の指定が行えますが、無指定ならば select * 相当の処理が行われます。

なおこの関数についても PK 指定のみを想定したものなので、Where などを使う際には別の方法を用いる必要があります。そちらも次回。

Insert と併せて実行した際の結果は次の通りです。

Delete の実装

最後に Delete です。これは Insert / Update と同じくレシーバとしての実装になっているので、事前に model の生成が必要となります。

Delete

Delete なので、実行結果は割愛します。

 

まとめ

・SQLBoiler は sqlboiler.toml に従って、DDL に (=DB上に存在するテーブル定義に) 沿った形で models を生成してくれる。

・SQLBoiler によって生成された models には既に基本的な CRUD を実行するだけの関数とレシーバが用意されており、基本的にユーザはそれを呼び出すだけでクエリを発行できる。

 

生クエリを書かずにクエリを発行できるなんて、便利ですね。
私はプログラムの中で SQL が一番好きなので、ちょっと寂しくはあるんですけれども。

ということで今回は、SQLBoiler の設定から基本 CRUD の実行までのまとめ記事でした。
次回は、応用編ということで Where の指定や Inner Join 、Outer Join などに触れていきたいと思います。

ここまでご覧いただき、ありがとうございました!

今回使用した src

以下に置いておきます。今後応用編を作るので、今回説明した以上のコードが混ざっているかもしれません。

https://github.com/NanairoMegane/sqlboiler_test

参考

https://github.com/volatiletech/sqlboiler

https://qiita.com/tenntenn/items/dddb13c15643454a7c3b

https://ken-aio.github.io/

https://note.crohaco.net/2020/golang-sqlboiler/

 

おすすめ書籍

Google Cloud Platform エンタープライズ設計ガイド

Google Cloud Platform 実践Webアプリ開発 ストーリーで学ぶGoogle App Engine

プログラマのためのGoogle Cloud Platform入門 サービスの全体像からクラウドネイティブアプリケーション構築まで

golangカテゴリの最新記事