Files
build-web-application-with-…/ja/05.5.md
2017-05-30 11:30:02 +08:00

250 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 5.5 beedbライブラリを使用してORM開発を行う
beedbは私が開発したGoによるORM操作のためのライブラリです。これはGo styleの方法でデータベースに対し操作を行います。structからテーブルの記録へのマッピングを実現します。beedbは十分軽量なGo ORMフレームワークです。このライブラリを開発した動機は複雑なORM学習曲線を引き下げたいと思ったからです。出来る限りORMの実行効率と機能の間でバランスをとったつもりです。beedbは現在オープンソースのGo ORMフレームワークの中で比較的完全なライブラリのひとつです。また、実行効率も相当良く、機能も基本的に需要を満足させています。しかし現在はまだアソシエーション関係をサポートしておらず、これは次のバージョンの主なポイントです。
beedbはdatabase/sql標準インターフェースをサポートしたORMライブラリです。そのため、理論上では、データベースドライバがdatabase/sqlインターフェースをサポートしていさえすればすんなりbeedbを使うことができます。現在までに私がテストしたドライバパッケージは以下のとおり
Mysql:github.com/ziutek/mymysql/godrv[*]
Mysql:github/go-mysql-driver/mysql[*]
PostgreSQL:github.com/lib/pq[*]
SQLite:github.com/mattn/go-sqlite3[*]
MS ADODB: github.com/mattn/go-adodb[*]
ODBC: bitbucket.org/miquella/mgodbc[*]
## インストール
beedbはgo get方式によるインストールをサポートしています。これはGo Styleの方式に完全に則って実装されています。
go get github.com/astaxie/beedb
## 初期化の方法
まず対応するデータベースドライバパッケージをimportする必要があります。database/sql標準インターフェースパッケージおよびbeedbパッケージです
import (
"database/sql"
"github.com/astaxie/beedb"
_ "github.com/ziutek/mymysql/godrv"
)
必要なパッケージをインポートした後、データベースへの接続を開く必要があります。その後beedbオブジェクトたとえばMySQLとしますを作成します
db, err := sql.Open("mymysql", "test/xiemengjun/123456")
if err != nil {
panic(err)
}
orm := beedb.New(db)
beedbのNew関数はつの引数を必要とします。一つ目の引数は標準インターフェースのdbで、二つ目の引数は利用するデータベースエンジンです。もしあなたが使用するデータベースエンジンがMySQL/Sqliteだった場合、二つ目の引数は省略してもかまいません。
もしSQLServerをお使いであれば、このように初期化する必要があります
orm = beedb.New(db, "mssql")
もしPostgreSQLをお使いであれば、初期化は以下のようになります
orm = beedb.New(db, "pg")
現在beedbはプリントデバッグをサポートしていますので、下のコードでデバッグを行うことができます。
beedb.OnDebug=true
以降の例では前のデータベースのテーブルUserinfoを採用します。まず目的のstructを作成します。
type Userinfo struct {
Uid int `PK` //もしテーブルのプライマリキーがidでなければ、pkコメントを追加する必要があります。このフィールドがプライマリキーであることを明示します。
Username string
Departname string
Created time.Time
}
>ご注意ください。beedbはキャメルケースの命名規則を自動でスネークケースのフィールドに変換します。たとえば`UserInfo`という名前のStructを定義した場合、低レイヤで実装される際に`user_info`と変換されます。フィールドの命名もこのルールに従います。
## データの挿入
下のコードはどのように記録を挿入するか示しています。我々が操作しているのはstructオブジェクトで、元々のsql文ではありません。Saveインターフェースをコールしてデータをデータベースに保存します。
var saveone Userinfo
saveone.Username = "Test Add User"
saveone.Departname = "Test Add Departname"
saveone.Created = time.Now()
orm.Save(&saveone)
挿入後、挿入に成功した際のインクリメンタルなIDが`saveone.Uid`です。Saveインターフェースは自動的に保存します。
beedbインターフェースはもう一種類の挿入の方法を提供しています。mapデータ挿入です。
add := make(map[string]interface{})
add["username"] = "astaxie"
add["departname"] = "cloud develop"
add["created"] = "2012-12-02"
orm.SetTable("userinfo").Insert(add)
複数のデータを挿入
addslice := make([]map[string]interface{}, 0)
add:=make(map[string]interface{})
add2:=make(map[string]interface{})
add["username"] = "astaxie"
add["departname"] = "cloud develop"
add["created"] = "2012-12-02"
add2["username"] = "astaxie2"
add2["departname"] = "cloud develop2"
add2["created"] = "2012-12-02"
addslice =append(addslice, add, add2)
orm.SetTable("userinfo").InsertBatch(addslice)
上の操作方法はメソッドチェーンによる検索にすこし似ています。jqueryに詳しい方はとても馴染みがあるのではないでしょうか。毎回コールされるmethodはすべてもともとのormオブジェクトを返しているので、継続してオブジェクトの他のmethodをコールすることができます。
上でコールしたSetTable関数はORMに対して、これから実行するこのmapに対応したデータベーステーブルが`userinfo`であると明示しています。
## データの更新
つづけて上の例で更新操作をご覧にいれましょう。現在saveoneのプライマリキーはすでに値が存在します。この時saveインターフェースをコールして、beedb内は自動的にupdateをコールすることによってデータの更新を行います。挿入操作ではありません。
saveone.Username = "Update Username"
saveone.Departname = "Update Departname"
saveone.Created = time.Now()
orm.Save(&saveone) //現在saveoneにはプライマリキーがあります。更新操作を行います。
データの更新はmap操作の直接の使用をサポートしています。
t := make(map[string]interface{})
t["username"] = "astaxie"
orm.SetTable("userinfo").SetPK("uid").Where(2).Update(t)
ここではいくつかのbeedbの関数をコールしてみます。
SetPKORMに対して、データベースのテーブル`userinfo`のプライマリキーが`uid`であることを明示します。
Where:条件を設定するために用いられます。複数の引数をサポートし、第一引数がもし整数であった場合、Where("プライマリキー=?",値)がコールされたものとなります。
Update関数はmap型のデータを受け取り、データの更新を実行します。
## データの検索
beedbの検索インターフェースは使いやすく、具体的な使用方法は下の例をご覧ください。
例1、プライマリキーによってデータを取得
var user Userinfo
//Whereは2つの引数を受け取ります。int型の引数をサポートします。
orm.Where("uid=?", 27).Find(&user)
例2
var user2 Userinfo
orm.Where(3).Find(&user2) // これは上の省略版です。プライマリキーは省略できます。
例3、プライマリキーではない条件
var user3 Userinfo
//Whereは2つの引数を受け取ります。文字列型の引数をサポートします。
orm.Where("name = ?", "john").Find(&user3)
例4、もっと複雑な条件
var user4 Userinfo
//Whereは3つの引数をサポートします。
orm.Where("name = ? and age < ?", "john", 88).Find(&user4)
下のインターフェースを通して複数のデータを取得できます。例をご覧ください。
例1、条件id>3にもとづいて、20からはじまる10件のデータを取得します。
var allusers []Userinfo
err := orm.Where("id > ?", "3").Limit(10,20).FindAll(&allusers)
例2、limitの第二引数は省略できます。デフォルトは0から開始となります。10件のデータを取得します。
var tenusers []Userinfo
err := orm.Where("id > ?", "3").Limit(10).FindAll(&tenusers)
例3、すべてのデータを取得します。
var everyone []Userinfo
err := orm.OrderBy("uid desc,username asc").FindAll(&everyone)
上ではLimit関数があります。これは検索結果の数をコントロールするのに用いられます。
Limit:2つの引数をサポートします。第一引数は検索数を表し、第二引数は取得するデータの開始位置を表しています。デフォルトは0です。
OrderBy:この関数は検索をソートするために用いられます。引数はソートの条件である必要があります。
上の例では取得するデータが直接structオブジェクトにマッピングされます。もし、データをmapとして取得したいだけであれば、下の方法で実現することができます
a, _ := orm.SetTable("userinfo").SetPK("uid").Where(2).Select("uid,username").FindMap()
上とこの例の中ではまた新しいインターフェースの関数Selectがでてきました。この関数はいくつのフィールドを検索したいのか定義するために用いられます。デフォルトでは全てのフィールドとなる`*`となります。
FindMap()関数は`[]map[string][]byte`型を返します。そのため、自分自身で型変換を行う必要があります。
## データの削除
beedbは豊富なデータ削除インターフェースを備えています。下の例をご覧ください。
例1、単一のデータを削除
//saveoneは上の例で示したあのsaveoneです。
orm.Delete(&saveone)
例2、複数のデータを削除
//alluserは上で定義した複数のデータのsliceです。
orm.DeleteAll(&alluser)
例3、sqlにしたがってデータを削除
orm.SetTable("userinfo").Where("uid>?", 3).DeleteRow()
## リレーション検索
現在beedbはstructのリレーションをサポートしていません。しかしいくつかのアプリケーションはリレーションによる検索を必要としています。そのため、現在beedbは簡単なソリューションを提供しています。
a, _ := orm.SetTable("userinfo").Join("LEFT", "userdeatail", "userinfo.uid=userdeatail.uid").Where("userinfo.uid=?", 1).Select("userinfo.uid,userinfo.username,userdeatail.profile").FindMap()
上のコードでは新しいインターフェースのJoin関数が出て来ました。この関数には3つの引数があります。
- 第一引数にはINNER, LEFT, OURTER, CROSS等が入れられます
- 第二匹数は接続するテーブルを表します
- 第三引数は接続の条件を表します
## Group ByとHaving
いくつかのアプリケーションがgroup byとhavingの機能を必要としているため、beedbも簡単な実現方法を提供しています。
a, _ := orm.SetTable("userinfo").GroupBy("username").Having("username='astaxie'").FindMap()
上のコードで現れる2つの新しいインターフェースの関数
GroupBy:groupbyのフィールドを実行するために用いられます
Having:havingを実行する際の条件を指定するために用いられます
## 一歩進んで
現在beedbはすでに多くの国内外からのユーザによってフィードバックを得ています。現在作り直しを考えています。以降ではいくつかの方面で改良が行われる予定です。
- interface設計の実装。database/sql/driverの設計に似て、beedbのインターフェースを設計します。その後対応するデータベースのCRUD操作を実現します。
- リレーショナルデータベースの設計の実現。一対一、一対多、多対多のサポートを実現します。コードは以下のとおり:
type Profile struct{
Nickname string
Mobile string
}
type Userinfo struct {
Uid int `PK`
Username string
Departname string
Created time.Time
Profile `HasOne`
}
- 自動的にデータベース、テーブル、インデックスを作成
- 接続プールの実現、goroutineを採用。
## links
* [目次](<preface.md>)
* 前へ: [PostgreSQLデータベースの使用](<05.4.md>)
* 次へ: [NOSQLデータベースの操作](<05.6.md>)