mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-27 03:20:25 +08:00
fix: 数据库实例删除,事务问题
This commit is contained in:
@@ -28,8 +28,8 @@
|
|||||||
"monaco-sql-languages": "^0.12.2",
|
"monaco-sql-languages": "^0.12.2",
|
||||||
"monaco-themes": "^0.4.4",
|
"monaco-themes": "^0.4.4",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^2.2.4",
|
"pinia": "^2.2.5",
|
||||||
"qrcode.vue": "^3.5.0",
|
"qrcode.vue": "^3.5.1",
|
||||||
"screenfull": "^6.0.2",
|
"screenfull": "^6.0.2",
|
||||||
"sortablejs": "^1.15.3",
|
"sortablejs": "^1.15.3",
|
||||||
"splitpanes": "^3.1.5",
|
"splitpanes": "^3.1.5",
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
"eslint": "^8.35.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-plugin-vue": "^9.28.0",
|
"eslint-plugin-vue": "^9.28.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"sass": "^1.80.3",
|
"sass": "^1.80.5",
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.6.3",
|
||||||
"vite": "^5.4.10",
|
"vite": "^5.4.10",
|
||||||
"vue-eslint-parser": "^9.4.3"
|
"vue-eslint-parser": "^9.4.3"
|
||||||
|
|||||||
@@ -160,27 +160,46 @@ func (ai *AppImpl[T, R]) CountByCond(cond any) int64 {
|
|||||||
return ai.GetRepo().CountByCond(cond)
|
return ai.GetRepo().CountByCond(cond)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行事务操作
|
// Tx 执行事务操作
|
||||||
func (ai *AppImpl[T, R]) Tx(ctx context.Context, funcs ...func(context.Context) error) (err error) {
|
func (ai *AppImpl[T, R]) Tx(ctx context.Context, funcs ...func(context.Context) error) (err error) {
|
||||||
tx := global.Db.Begin()
|
tx := contextx.GetTx(ctx)
|
||||||
dbCtx := contextx.WithDb(ctx, tx)
|
dbCtx := ctx
|
||||||
|
var txDb *gorm.DB
|
||||||
|
|
||||||
|
if tx == nil {
|
||||||
|
txDb = global.Db.Begin()
|
||||||
|
dbCtx, tx = contextx.WithTxDb(ctx, txDb)
|
||||||
|
} else {
|
||||||
|
txDb = tx.DB
|
||||||
|
tx.Count++
|
||||||
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
txDb.Rollback()
|
||||||
|
contextx.RmDb(ctx)
|
||||||
|
err = fmt.Errorf("%v", r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.Count--
|
||||||
|
if tx.Count < 1 {
|
||||||
// 移除当前已执行完成的的数据库事务实例
|
// 移除当前已执行完成的的数据库事务实例
|
||||||
contextx.RmDb(ctx)
|
contextx.RmDb(ctx)
|
||||||
if r := recover(); r != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
err = fmt.Errorf("%v", err)
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for _, f := range funcs {
|
for _, f := range funcs {
|
||||||
err = f(dbCtx)
|
err = f(dbCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tx.Rollback()
|
tx.Count = 0
|
||||||
|
txDb.Rollback()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = tx.Commit().Error
|
|
||||||
|
if tx.Count == 1 {
|
||||||
|
err = txDb.Commit().Error
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,28 +49,56 @@ func GetTraceId(ctx context.Context) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将事务db放置context中,使用stack保存。以便多个方法调用实现方法内部各自的事务操作
|
// Tx 事务上下文信息
|
||||||
func WithDb(ctx context.Context, db *gorm.DB) context.Context {
|
type Tx struct {
|
||||||
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*gorm.DB]); ok {
|
Count int
|
||||||
dbStack.Push(db)
|
DB *gorm.DB
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
dbStack := new(collx.Stack[*gorm.DB])
|
|
||||||
dbStack.Push(db)
|
|
||||||
|
|
||||||
return context.WithValue(ctx, DbKey, dbStack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前操作的栈顶事务数据库实例
|
func (t *Tx) Rollback() {
|
||||||
|
if t.Count == 0 {
|
||||||
|
t.DB.Rollback()
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTxDb 将事务db放置context中,使用stack保存。以便多个方法调用实现方法内部各自的事务操作
|
||||||
|
func WithTxDb(ctx context.Context, db *gorm.DB) (context.Context, *Tx) {
|
||||||
|
tx := &Tx{Count: 1, DB: db}
|
||||||
|
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*Tx]); ok {
|
||||||
|
dbStack.Push(tx)
|
||||||
|
return ctx, tx
|
||||||
|
}
|
||||||
|
dbStack := new(collx.Stack[*Tx])
|
||||||
|
dbStack.Push(tx)
|
||||||
|
|
||||||
|
return context.WithValue(ctx, DbKey, dbStack), tx
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDb 获取当前操作的栈顶事务数据库实例
|
||||||
func GetDb(ctx context.Context) *gorm.DB {
|
func GetDb(ctx context.Context) *gorm.DB {
|
||||||
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*gorm.DB]); ok {
|
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*Tx]); ok {
|
||||||
return dbStack.Top()
|
if tx := dbStack.Top(); tx != nil {
|
||||||
|
return tx.DB
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RmDb(ctx context.Context) *gorm.DB {
|
// GetTx 获取当前操作的栈顶事务信息
|
||||||
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*gorm.DB]); ok {
|
func GetTx(ctx context.Context) *Tx {
|
||||||
|
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*Tx]); ok {
|
||||||
|
if tx := dbStack.Top(); tx != nil {
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RmDb 删除数据库事务db
|
||||||
|
func RmDb(ctx context.Context) *Tx {
|
||||||
|
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*Tx]); ok {
|
||||||
return dbStack.Pop()
|
return dbStack.Pop()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user