Gin实战7:事务管理升级!Biz层接管事务控制

一、引言
上一次我们已经实现了通过Gorm Gen实现数据库基础操作,在之前的代码结构中,Data 层负责实现数据操作,而Biz层则专注于业务逻辑处理。 但实际开发中经常会需要开启事务处理多个表的操作,此时需要考虑事务控制方案。如果事务控制在Data层实现,许多业务层的逻辑就不得不放到Data层,Data层将会变得非常臃肿。 因此我们需要考虑将事务控制移到Biz层,以实现更清晰、更易维护的代码结构。
二、将事务控制移到Biz层
-
Biz层事务控制的好处
- 可以清晰地分离数据操作和事务控制,提高代码可维护性
- 数据层无感知开启事务,专注于数据处理。
- 数据层的事务控制逻辑可以复用,减少重复代码。
-
如何实现? 事务处理的核心思想是:在业务逻辑中,通过上下文传递事务对象,并在需要时开启事务,并在业务逻辑执行完成后提交或回滚事务。 我们同样借鉴kratos/example 中的[transaction] 部分的实现方案。
三、实战改造步骤
- Biz层实现
- 新增 Transaction 接口 定义
type Transaction interface {
QueryTx(context.Context, func(ctx context.Context) error) error
}
- Data层实现 Transaction
- 事务上下文传递方案(context传递事务对象)
type contextQueryTxKey struct{}
type Data struct {
db *gorm.DB
}
func (d *Data) DB(ctx context.Context) *query.Query {
tx, ok := ctx.Value(contextQueryTxKey{}).(*query.Query)
if ok {
return tx
}
return query.Use(d.db)
}
func (d *Data) QueryTx(ctx context.Context, fn func(ctx context.Context) error) error {
q := query.Use(d.db)
return q.Transaction(func(tx *query.Query) error {
ctx = context.WithValue(ctx, contextQueryTxKey{}, tx)
return fn(ctx)
})
}
- Biz层使用事务
a.tx.QueryTx(ctx, func(ctx context.Context) error {
// todo
})
需要注意的是data 层需要用 DB(ctx)
方法获取Query对象
总结
- 通过将事务控制移到Biz层,实现了更清晰、更易维护的代码结构。
- 通过上下文传递事务对象,在需要时开启事务,并在业务逻辑执行完成后提交或回滚事务,实现了事务控制的核心思想。
感谢你的关注和支持,回复【Gin实战】 获取完整代码
