事务接口定义
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.