Gormでトランザクションを実装する

Gormでトランザクションを利用する時の覚書。

DBとの接続およびトランザクションの開始

以下ではTranscation関数を定義し、その中でCRUDの処理を実行するようにしている。 そして、deferでは最終的にTransaction関数から返ってきたerrがnilかどうかを見てロールバックするかコミットするかを判断している。

// main.go

func main() {
  DBMS := "mysql"
  USER := "root"
  PASS := "mysql"
  PROTOCOL := "tcp(localhost:3306)"
  DBNAME := "sampleDB"

  CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME
  db, err := gorm.Open(DBMS, CONNECT)
  if err != nil {
    panic(err.Error())
  }

  tx := db.Begin()
  // Transaction関数が存在し、その引数にはトランザクションの情報とCreate処理を盛り込んだ関数を渡す
  err := Transaction(tx, createFunc)
  defer func() {
    if err != nil {
      tx.Rollback()
    } else {
      tx.Commit()
    }
  }
}

Transaction関数の中身とその引数となるcreateFunc関数

// main.go

type CreateFunc func(tx *gorm.DB) error

func Transaction(
  tx *gorm.DB,
  createFunc CreateFunc,
) error {
  // create処理を行う
  err := createFunc(tx)
  // create処理が失敗したらRollbackさせるためにerrを返す
  return err
}

// createFuncではなんらかのCreate処理を行う
func createFunc(tx *gorm.DB) error {
  creature := Creature{Name: "Human", Type: "Mammal"}
  tx.NewRecord(creature)
  return tx.Create(&creature).Error // 適宜必要な戻り値があればそれも盛り込んで返すようにする
}

Createに加えてupdateやdeleteなどの他の処理も行いたい場合はcreateFuncのように処理を書いて、Transaction関数内に追加していく。