事务

基本机制

创建数据库连接之后,我们使用该数据库连接创建事务管理器。

db := rdb.Connect("local.properties")
tm := rdb.NewTransactionManager(db)

GoooQo中的事务管理通过TransactionManagerTransactionContext(以下简称TC)配合完成。

package core

import (
	"context"
	"database/sql/driver"
)

type TransactionManager interface {
	GetClient() any
	StartTransaction(ctx context.Context) (TransactionContext, error)
	SubmitTransaction(ctx context.Context, callback func(tc TransactionContext) error) error
}

type TransactionContext interface {
	context.Context
	driver.Tx
	Parent() context.Context
	SavePoint(name string) error
	RollbackTo(name string) error
}

TransactionManager中的方法StartTransaction负责开启事务并返回TC;TC组合了driver.Tx,负责事务的提交和回滚。

TxDataAccess接口组合了DataAccessTransactionManager,可以在实现数据库访问接口的同时,更方便的进行事务管理。

type TxDataAccess[E Entity] interface {
	TransactionManager
	DataAccess[E]
}

事务使用示例

使用TransactionManager#StartTransaction开启事务,手动提交或者回滚事务:

tc, err := userDataAccess.StartTransaction(ctx)
userQuery := UserQuery{ScoreLt: P(80)}
cnt, err := userDataAccess.DeleteByQuery(tc, userQuery)
if err != nil {
	err = RollbackFor(tc, err)
	return 0
}
err = tc.Commit()
return cnt

或者使用TransactionManager#SubmitTransaction通过回调的方式提交事务:

err := tm.SubmitTransaction(ctx, func(tc TransactionContext) (err error) {
    // transaction body
    return
})

事务的传播管理

在Spring的事务传播机制中定义了以下7个级别,GoooQo中的对应处理方式如下:

  • REQUIRED

    使用任意context调用TxDataAccessStartTransaction

    如果context为TC,则将context强制转化为TC后返回;

    如果context不是TC,则调用db#BeginTx开启事务获取sql.Tx,再通过context和sql.Tx创建TC后返回。

  • SUPPORTS

    使用任意Context调用TxDataAccess的数据库访问方法。

  • REQUIRES_NEW

    ctx为TC时,使用ctx.(TC).Context开启事务; 当ctx不为TC时,使用ctx开启事务;

  • NOT_SUPPORTED

    ctx为TC时,使用ctx.(TC).Context调用TxDataAccess的数据库访问方法; 当ctx不为TC时,使用ctx调用TxDataAccess的数据库访问方法;

  • MANDATORY:

    对传入的ctx不是TC的情况进行处理。

  • NEVER

    对传入的ctx是TC的情况进行处理。

  • NESTED

    使用TC的SavePoint/RollbackTo方法。

这里整理了一个表格对前4个传播级别进行了对比:

最后更新于