事务接口定义
GoooQo中的事务管理通过TransactionManager和TransactionContext(以下简称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接口组合了DataAccess和TransactionManager,可以在实现数据库访问接口的同时,更方便的进行事务管理。
type TxDataAccess[E Entity] interface {
TransactionManager
DataAccess[E]
}
事务使用示例
用户可以使用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调用
TxDataAccess的StartTransaction:如果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个传播级别进行了对比:
| context参数\数据库操作 | 开启事务 | 调用数据库 |
|---|---|---|
| 任意Context | REQUIRED | SUPPORTS |
| ctx.(TC).Context | ctx | REQUIRES_NEW | NOT_SUPPORTED |
总结
虽然由于Golang语法限制,无法实现类似SpringTx提供的基于注解的管理事务传播级别的方法,
但是GoooQo利用了Golang的Context机制达到了同样的效果,使得开发人员能够使用最少的代码来对事务的传播级别进行对应的处理。
© 2024 Yuan Zhen. All rights reserved.