0

我在我的一个 Golang 应用程序中有一个用例来更新 API 中的多个表,如果其中一个更新失败,我希望所有以前的更新都回滚(Java 中的 @Transactional 所做的事情)。我尝试通过以下方式进行操作:

func (d *dao) Method1(opt string) error {
    tx, err := d.DB.BeginTx(context.Background(), nil)
    if err != nil {
        return errors.Errorf("Unable to start transaction")
    }
    err := d.dao1.Update1(opt)
        if err != nil {
            log.Infof("Error : %s. Rolling back transaction", err)
            _ = tx.Rollback()
            log.Infof("Transaction rolled back while update 1")
            return err
        }
        err = d.dao2.Update2(opt)
        if err != nil {
            log.Errorf("Error in making update 2 "+
                "Error %v ", err)
            _ = tx.Rollback()
            log.Infof("Transaction rolled back while update 2")
            return err
        }
    }
}


func(d *dao1) Update1 error {
        var query = "update T1 set C1 = ? where id = ?"
        _, err := d.DB.Exec(query, "v1", "v2")
        return err
}

func(d *dao2) Update2 error {
        var query = "update T2 set C2 = ? where id = ?"
        _, err := d.DB.Exec(query, "v1", "v2")
        return err
}

但这不起作用,因为我们在 Update1 和 Update2 方法中创建了一个新事务。所以我尝试在方法 Update1 和 Update2 的方法参数中传递事务,如下所示:

func Update1(tx sql.Tx) error {
    var query = "update T1 set C1 = ? where id = ?"
    _, err := tx.Exec(query, "v1", "v2")
    return err
}

但问题是在某些用例中,我只想调用方法 Update1。在这种情况下,要在 Update1 方法中传递的事务的值应该是多少?

或者有没有更好的方法来做到这一点。有人可以帮忙吗?

4

1 回答 1

0

如果我理解正确,在某些情况下您希望Update1被调用但不是Update2,而在其他情况下您希望两个更新都发生。如果是这样的话,那么我建议这更多是一个设计问题,而不是使用Tx. 我认为设计两个函数,每个函数都描述您期望的行为,并将关于调用哪个函数的逻辑委托给调用者,可能会起作用。就像是:

func Caller() error {
    if condition {
        return UpdateOne()
    }
    return UpdateBoth()
}

func UpdateOne() error { … }
func UpdateBoth() error { … }
于 2021-04-19T13:29:06.373 回答