Closed kolkov closed 8 years ago
This is the code I wrote for a project. You can use this handler (middleware) for any request that needs transaction. GetContext()
retrieves some application-specific context information from routing.Context
. You will need to pass along this context through all methods that need to do DB operations (this is because transaction is something per request).
import (
"github.com/go-ozzo/ozzo-dbx"
"github.com/go-ozzo/ozzo-routing"
"github.com/go-ozzo/ozzo-routing/fault"
)
// Transactional starts a DB transaction.
// If a nested handler returns an error or a panic happens, it will rollback the transaction.
// Otherwise it will commit the transaction after the nested handlers finish execution.
// By calling app.Context.SetRollback(true), you may also explicitly request to rollback the transaction.
func Transactional(db *dbx.DB) routing.Handler {
return func(c *routing.Context) error {
tx, err := db.Begin()
if err != nil {
return err
}
ac := GetContext(c)
ac.SetTx(tx)
err = fault.PanicHandler(ac.Errorf)(c)
var e error
if err != nil || ac.Rollback() {
// rollback if a handler returns an error or rollback is explicitly requested
e = tx.Rollback()
} else {
e = tx.Commit()
}
if e != nil {
if err == nil {
// the error will be logged by an error handler
return e
}
// log the tx error only
ac.Error(e)
}
return err
}
}
For your reference, I just published this repo: https://github.com/qiangxue/golang-restful-starter-kit
Great thanks! Very interesting, with DAO layer and errors handling! ))
Hi! How to use transactions when database queries located in different methods? Like in my case? Or I must using this in handler functions?