前提
- Go言語そのものに慣れていない
- MySQLはVagrantで適当にCentOS6.6に構築
- 単純検索ぐらいはできるようになった
今回のTODO
- 登録・更新・削除できるようになる
- トランザクション制御ができるようになる
- 登録時のPKを取得する
いざ実践!
- 概略は理解した(つもり)なので、サンプルを見ながら実装
問題点
- 登録時のPKを取得数方法がわからない
- tx.Create の戻り値の中に Value があるが、interface{} でリフレクションしたくない
解決策
- 検索結果をstructに変換するメソッドで解決できた
db_connection2.go
// DBアクセスsample2.go
package main
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
type User struct {
ID uint64 `gorm:"primary_key"`
Email string `gorm:"type:varchar(255);"`
Name string `gorm:"type:varchar(45);"`
}
func main() {
db, err := gorm.Open("mysql", "testuser:testuser@/go_sample?charset=utf8&parseTime=True&loc=Local")
if err != nil {
panic("failed to connect database")
}
// テーブル名が複数系でない場合、これを指定すること
db.SingularTable(true)
// 実行ログ出力
// db.LogMode(true)
// 最新のIDを取得してインサートすると見せかけてロールバックする
var user User
var id uint64 = lastPrint(db, user)
tx := db.Begin()
var sid = fmt.Sprint(id)
user = User{Email: "sample@" + sid + "test.com", Name: "Name" + sid}
savePrint(tx, user)
tx.Rollback()
// 更新されていないことを確認
lastPrint(db, user)
tx = db.Begin()
id, err = savePrint(tx, user)
// 本来はエラーならロールバック
tx.Commit()
// 更新されていることを確認
lastPrint(db, user)
// 更新メソッドが実行されることを確認
tx = db.Begin()
user.ID = id
savePrint(tx, user)
tx.Commit()
// レコードが追加されていないことを確認
lastPrint(db, user)
// 削除されることを確認
tx = db.Begin()
tx.Delete(user)
tx.Commit()
// 削除されていることを確認
user.ID = uint64(0)
lastPrint(db, user)
}
func lastPrint(db *gorm.DB, user User) uint64 {
var count int
db.Last(&user).Count(&count)
if count == 0 {
fmt.Println("該当レコードなし")
} else {
fmt.Println("id:" + fmt.Sprint(user.ID))
}
return user.ID
}
// 本当は Save を使えば事足りるはず
func savePrint(tx *gorm.DB, user User) (uint64, error) {
// 戻り値用の変数定義
var rId uint64 = 0
// PKを設定しないと true を返すらしい
if tx.NewRecord(user) {
fmt.Println("\t新規レコードです。")
result := tx.Create(&user)
if result.Error != nil {
return rId, result.Error
}
// 追加したIDが欲しい場合、Scanで元の形に変換する
result.Scan(&user)
sid := fmt.Sprint(user.ID)
fmt.Println("\t新規追加したID:" + sid)
rId = user.ID
} else {
fmt.Println("\t更新レコードです。")
rId = user.ID
result := tx.Model(&user).Update(&user)
if result.Error != nil {
return rId, result.Error
}
sid := fmt.Sprint(user.ID)
fmt.Println("\t更新したID:" + sid)
}
return rId, nil
}
残課題
- 件数をわざわざ取得しないで存在しないチェックを行いたい
- ID == 0 でも良いけれど、美しくない
- 検索条件の初期化の際に ID = 0 以外の方法を探す
TODO
- 複雑な検索結果の取得
- リレーションの貼り方、概念的な整理
- ソースの自動生成