• ent 基本使用十九 事务处理


    ent 生成的代码中client 提供了比较全的事务处理

    启动单个事务进行处理

    // GenTx generates group of entities in a transaction.
    func GenTx(ctx context.Context, client *ent.Client) error {
        tx, err := client.Tx(ctx)
        if err != nil {
            return fmt.Errorf("starting a transaction: %v", err)
        }
        hub, err := tx.Group.
            Create().
            SetName("Github").
            Save(ctx)
        if err != nil {
            return rollback(tx, fmt.Errorf("failed creating the group: %v", err))
        }
        // Create the admin of the group.
        dan, err := tx.User.
            Create().
            SetAge(29).
            SetName("Dan").
            AddManage(hub).
            Save(ctx)
        if err != nil {
            return rollback(tx, err)
        }
        // Create user "Ariel".
        a8m, err := tx.User.
            Create().
            SetAge(30).
            SetName("Ariel").
            AddGroups(hub).
            AddFriends(dan).
            Save(ctx)
        if err != nil {
            return rollback(tx, err)
        }
        fmt.Println(a8m)
        // Output:
        // User(id=2, age=30, name=Ariel)
        // Commit the transaction.
        return tx.Commit()
    }
    // rollback calls to tx.Rollback and wraps the given error
    // with the rollback error if occurred.
    func rollback(tx *ent.Tx, err error) error {
        if rerr := tx.Rollback(); rerr != nil {
            err = fmt.Errorf("%v: %v", err, rerr)
        }
        return err
    }
     
     

    事务client 封装

    有时已经使用了 *ent.Client 但是我们需要支持事务,就可以使用次方法

    // WrapGen wraps the existing "Gen" function in a transaction.
    func WrapGen(ctx context.Context, client *ent.Client) error {
        tx, err := client.Tx(ctx)
        if err != nil {
            return err
        }
        txClient := tx.Client()
        // Use the "Gen" below, but give it the transactional client; no code changes to "Gen".
        if err := Gen(ctx, txClient); err != nil {
            return rollback(tx, err)
        }
        return tx.Commit()
    }
    // Gen generates a group of entities.
    func Gen(ctx context.Context, client *ent.Client) error {
        // ...
        return nil
    }
     
     

    最佳实践

    • 一个可重用的事务帮助方法
    func WithTx(ctx context.Context, client *ent.Client, fn func(tx *ent.Tx) error) error {
        tx, err := client.Tx(ctx)
        if err != nil {
            return err
        }
        defer func() {
            if v := recover(); v != nil {
                tx.Rollback()
                panic(v)
            }
        }()
        if err := fn(tx); err != nil {
            if rerr := tx.Rollback(); rerr != nil {
                err = errors.Wrapf(err, "rolling back transaction: %v", rerr)
            }
            return err
        }
        if err := tx.Commit(); err != nil {
            return errors.Wrapf(err, "committing transaction: %v", err)
        }
        return nil
    }
     
     
    • 使用
    func Do(ctx context.Context, client *ent.Client) {
        // WithTx helper.
        if err := WithTx(ctx, client, func(tx *ent.Tx) error {
            return Gen(ctx, tx.Client())
        }); err != nil {
            log.Fatal(err)
        }
    }

    参考资料

    https://entgo.io/docs/transactions/

  • 相关阅读:
    转载高效的MySQL分页 枫
    [笔记]NFC笔记——WUP_REQ 和 WUP_RES 消息结构
    [笔记]NFC笔记——PSL_REQ 和 PSL_RES 消息结构
    [笔记]C语言中二级指针简单例子
    [笔记]NFC协议规范学习笔记汇总
    [笔记]C语言中预定义符 __FILE__, __LINE__, __FUNCTION__, __DATE__, __TIME__ 的使用演示
    [笔记]如何限制用户在5分钟之后才能重复同样操作
    [笔记]NFC笔记——ATR_RES 消息结构
    简单的具备自动检测行为的文本框控件
    多重AutoComplete的Textbox
  • 原文地址:https://www.cnblogs.com/rongfengliang/p/11678251.html
Copyright © 2020-2023  润新知