目次
Go言語のトランザクション処理
Go言語でトランザクション処理をやります。
DBはMariaDB(MySQL)で、DBはインストールしてある前提です。
環境はWindows10/VSCodeを使ってます。
MySQLドライバのインストールなどを(1)で行った続きになります。
前回は、DBの操作に、「 database/sql」パッケージを使いました。
しかし、「 database/sql」パッケージはSelectの結果を構造体で受けられないなど、使い勝手が悪い部分があります。
sqlx
今回はその拡張版である「sqlx」を使います。
sqlxのインストール
sqlxを使うには、go getでインストールして
go get github.com/jmoiron/sqlx
以下をインポートします。
"github.com/jmoiron/sqlx"
とりあえず、あれこれ欲張ってもしょうがないので、今回は以下の3つだけやります。
- sqlxでデータベースオープンする
- sqlxでトランザクション内で更新系(insert、update、delete)を実行する
- sqlxでSelect文でデータを取得して構造化データに結果を格納する
やり方を確認します。
sqlxでデータベースオープンする
データベースオープンは、前回の「 database/sql」の時とほぼ同じやり方です。
構文
dbx, err := sqlx.Open("mysql", "user_id:password@tcp(localhost:3306)/dbname")
引数は
ですので、環境にあわせて変更します。
sqlxトランザクションでinsert、update、deleteを実行する
上記のようにオープンした「dbx」があるとすると。
1.トランザクションを開始する。
tx := dbx.MustBegin()
tx.MustExec("insert into gotest values(?,?)", id, name+strconv.Itoa(id))
tx.MustExec("update gotest set name=? where id < 5", "IDが5より小さい")
tx.MustExec("delete from gotest")
3.コミットする
tx.Commit()
の組み合わせで実行します。
sqlxでSelect文でデータを取得して構造化データに結果を格納する
Select結果をうける構造体を以下のように定義したとして。
type Results struct {
Id int
Name string
}
その構造体の配列を作り
rows := []Results{}
その配列のポインタを渡してSelectを実行すると、結果用の構造体の配列に値をセットしてくれます。
dbx.Select(&rows, "select id,name from gotest where id <= 10")
とりあえず、これで一通りのことはできます。
前回と同じ処理をsqlxで書き直したサンプル
前回(1)の時のサンプルと全く同じ処理を、sqlxの上記を使って書き直します。
前回のリンクはこちらです。
以下、それをsqlxを使って書き直したものです。
package main import ( "fmt" "strconv" "time" _ "github.com/go-sql-driver/mysql" "github.com/jmoiron/sqlx" ) func blog02() { // MariaDBを開きます。 dbx, dberr := sqlx.Open("mysql", "bltuser:bltpass@tcp(localhost:3306)/bltdb") if dberr != nil { println("データベースオープンに失敗しました") panic(dberr) } defer dbx.Close() // タイムアウトは3分に設定 dbx.SetConnMaxLifetime(time.Minute * 3) // 接続数はとりあえず10に設定 dbx.SetMaxOpenConns(10) dbx.SetMaxIdleConns(10) tx := dbx.MustBegin() var name = "テスト文字列:その" for id := 1; id < 10; id++ { tx.MustExec("insert into gotest values(?,?)", id, name+strconv.Itoa(id)) } tx.Commit() type Results struct { Id int Name string } rows := []Results{} dbx.Select(&rows, "select id,name from gotest where id <= 10") for i, _ := range rows { fmt.Printf("取得したIDは「%d」:NAMEは「%s」です。\n", rows[i].Id, rows[i].Name) } tx2 := dbx.MustBegin() tx2.MustExec("update gotest set name=? where id < 5", "IDが5より小さい") tx2.Commit() rows2 := []Results{} dbx.Select(&rows2, "select id,name from gotest where id <= 10") for _, s := range rows2 { fmt.Printf("更新後に取得したIDは「%d」:NAMEは「%s」です。\n", s.Id, s.Name) } tx3 := dbx.MustBegin() tx3.MustExec("delete from gotest") tx3.Commit() } func main() { blog02() }
劇的にすっきりしました。
Selectの結果を構造体の配列にセットしてくれるので、後処理も普通にrangeを使って配列のループとして回して処理できるのもやりやすいです。
個人的には、我慢して「 database/sql」を使う理由はないです。
SQL文を生成できれば、これで一通り基本的なデータ取得と更新はできそうです。
ではでは。