数据库 SQL 事务
启动事务
bun.Tx
是 sql.Tx
的一个薄包装器。除了 sql.Tx
提供的功能外,bun.Tx
还支持 查询钩子 并提供帮助程序来构建查询。
type Tx struct {
*sql.Tx
db *DB
}
要启动事务
tx, err := db.BeginTx(ctx, &sql.TxOptions{})
要提交/回滚事务
err := tx.Commit()
err := tx.Rollback()
在事务中运行查询
就像使用 bun.DB
一样,您可以使用 bun.Tx
来运行查询
res, err := tx.NewInsert().Model(&models).Exec(ctx)
res, err := tx.NewUpdate().Model(&models).Column("col1", "col2").Exec(ctx)
err := tx.NewSelect().Model(&models).Limit(100).Scan(ctx)
RunInTx
Bun 提供 RunInTx
帮助程序,这些帮助程序在事务中运行提供的函数。如果函数返回错误,则回滚事务。否则,提交事务。
err := db.RunInTx(ctx, &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
_, err := tx.Exec(...)
return err
})
IDB 接口
Bun 提供 bun.IDB
接口,因此相同的方法可以与 *bun.DB
、bun.Tx
和 bun.Conn
一起使用。以下 示例 演示了 InsertUser
如何使用 bun.IDB
来支持事务
// Insert single user using bun.DB.
err := InsertUser(ctx, db, user1)
// Insert several users in a transaction.
err := db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
if err := InsertUser(ctx, tx, user1); err != nil {
return err
}
if err := InsertUser(ctx, tx, user2); err != nil {
return err
}
return nil
})
func InsertUser(ctx context.Context, db bun.IDB, user *User) error {
_, err := db.NewInsert().Model(user).Exec(ctx)
return err
}
PostgreSQL 咨询锁
您可以使用以下代码获取 PostgreSQL 咨询锁
err := db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
if _, err := tx.ExecContext(ctx, "SELECT pg_advisory_xact_lock(1)"); err != nil {
return err
}
if _, err := db.NewSelect().ColumnExpr("pg_advisory_xact_lock(2)").Exec(ctx); err != nil {
return err
}
return nil
})