Go ORM框架XORM事务的示例

说明

  • XORM文档
  • xorm-plus,xorm的增强版本,支持嵌套式事务
  • 使用的是sqlite数据库
  • 语句orm.ShowSQL(true)是打开xorm的sql日志
  • 语句err = orm.Sync2(new(User))是同步User的字段信息到数据库的schema
  • 重点在于defer 语句,defer 语句是用来延迟执行函数的,而且延迟发生在调用函数 return 之后,被 defer 修饰的函数在 return 之后执行,这个时机点正好可以捕获函数抛出的 panic,因而 defer 的另一个重要用途就是执行 recover。recover 只有在 defer 中使用才更有意义,如果在其他地方使用,由于 program 已经调用结束而提前返回而无法有效捕捉错误。defer 的作用就是把关键字之后的函数执行压入一个栈中延迟执行,多个 defer 的执行顺序是后进先出 LIFO(Last In First Out后进先出),此处在defer中判断是否有抛出panic,如果抛出错误,执行回滚,如果函数返回错误,也执行回滚,否则执行commit操作

示例代码

import (
    "fmt"
    "github.com/go-xorm/xorm"
    _ "github.com/mattn/go-sqlite3"
    "time"
)
// User is our user table structure.
type User struct {
    ID        int64  // auto-increment by-default by xorm
    Version   string `xorm:"varchar(200)"`
    Salt      string
    Username  string
    Password  string    `xorm:"varchar(200)"`
    Languages string    `xorm:"varchar(200)"`
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
}

func TestXORM() {
    orm, err := xorm.NewEngine("sqlite3", "./test.db")
    if err != nil {
        panic(err)
    }
    orm.ShowSQL(true)
    err = orm.Sync2(new(User))

    session := orm.NewSession()

    addUser(session)

}


type ORMOperation func(session *xorm.Session) error

func Transaction(session *xorm.Session, f ORMOperation) (err error) {
    err = session.Begin()
    if err != nil {
        return
    }
    defer func() {
        if p := recover(); p != nil {
            fmt.Printf("recover rollback:%s\r\n",p)
            session.Rollback()
            panic(p) // re-throw panic after Rollback
        } else if err != nil {
            fmt.Printf("error rollback:%s\r\n",err)
            session.Rollback() // err is non-nil; don't change it
        } else {
            err = session.Commit() // err is nil; if Commit returns error update err
        }
    }()
    err = f(session)
    return err
}



func addUser(session *xorm.Session) error {
    //Transaction 的 f 参数类型为 ORMOperation,
    // addUser 和 ORMOperation 函数类型相同的参数和返回值,
    // 因此可以将 addUser 函数作为参数传入 Transaction 函数中。
    return Transaction(session, func(session *xorm.Session) error {
        if _,error := session.Insert(User{ID:5,Version:"abc"}); error != nil{
            return error
        }

        if _,error := session.Insert(User{ID:6,Version:"bcd"}); error != nil{
            return error
        }

        if _,error := session.Insert(User{ID:4,Version:"cde"}); error != nil{
            return error
        }

        return nil
    })
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。