事务化突变
在本部分我们继续 GraphQL 示例 来解释如何将 GraphQL 突变设置为事务化的。 这意味着最终将 GraphQL 突变自动化包装为数据库事务及其提交,或在 GraphQL 报错时回滚事务。
克隆代码(可选)
本教程代码可以在 github.com/a8m/ent-graphql-example 找到,
并在每一步都打了标签(使用 Git)。
如果你想要跳过基础安装并使用 GraphQL 最初的版本,你可以像如下克隆代码仓库并签出 v0.1.0 版本:
git clone git@github.com:a8m/ent-graphql-example.git
cd ent-graphql-example
go run ./cmd/todo/
使用
GraphQL 提供名为 entgql.Transactioner 处理器,用来在事务中执行每一个 GraphQL 突变。 解析器的注入客户端是一个 [事务化 ent.Client](code-generation-transactions.md#事务客户端)。 因此使用 ent.Client` 的 GraphQL 解析器无需改变。
我们通过以下步骤将它添加到待办事项列表应用程序中:
1. 编辑 cmd/todo/main.go 并将 entgql.Transactioner 处理器添加到 GraphQL 服务器初始化中,如下:
srv := handler.NewDefaultServer(todo.NewSchema(client))
+srv.Use(entgql.Transactioner{TxOpener: client})
2. 然后在 GraphQL 突变中使用上下文中获取的客户端,如下:
}
+func (mutationResolver) CreateTodo(ctx context.Context, input ent.CreateTodoInput) (*ent.Todo, error) {
+ client := ent.FromContext(ctx)
+ return client.Todo.Create().SetInput(input).Save(ctx)
-func (r *mutationResolver) CreateTodo(ctx context.Context, input ent.CreateTodoInput) (*ent.Todo, error) {
- return r.client.Todo.Create().SetInput(input).Save(ctx)
}
隔离级别
如果你想要调整事务隔离级别,可以通过实现自己的 TxOpener 来做到。例如:
srv.Use(entgql.Transactioner{
TxOpener: entgql.TxOpenerFunc(func(ctx context.Context) (context.Context, driver.Tx, error) {
tx, err := client.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelRepeatableRead})
if err != nil {
return nil, nil, err
}
ctx = ent.NewTxContext(ctx, tx)
ctx = ent.NewContext(ctx, tx.Client())
return ctx, tx, nil
}),
})
跳过操作
默认情况下 entgql.Transactioner 将所有突变包装为一个事务。
但是有些突变或操作不需要访问数据库或特殊的处理。
这种情况下,你可以通过设置自定义 SkipTxFunc 函数或使用内置函数之一使 entgql.Transactioner 跳过事务。
srv.Use(entgql.Transactioner{
TxOpener: client,
// Skip the given operation names from running under a transaction.
SkipTxFunc: entgql.SkipOperations("operation1", "operation2"),
})
srv.Use(entgql.Transactioner{
TxOpener: client,
// Skip if the operation has a mutation field with the given names.
SkipTxFunc: entgql.SkipIfHasFields("field1", "field2"),
})
srv.Use(entgql.Transactioner{
TxOpener: client,
// Custom skip function.
SkipTxFunc: func(*ast.OperationDefinition) bool {
// ...
},
})
很好!通过几行代码我们的应用程序现在支持自动化事务突变了。 请继续下一部分,我们将解释如何为 GraphQL 突变扩展 Ent 代码生成器并生成 GraphQL 输入类型。