如何使用sqlc搭配pgx(PostgreSQL)处理事务?微服务集成疑问
在微服务中用sqlc集成事务:无需同时传入连接池和Queries实例
你不需要同时在仓库里持有连接池(pgx.Pool)和Queries实例,只需要持有连接池就足够覆盖普通操作和事务操作的场景。
原因分析
你提供的query包中,DBTX接口同时被pgx.Pool和pgx.Tx实现:
- 普通操作时,连接池本身就可以作为
DBTX参数传入query.New()生成Queries实例 - 事务操作时,通过连接池开启事务得到
pgx.Tx,再调用Queries.WithTx()就能生成绑定了事务的Queries实例
改造你的仓库结构
把原来的OrgRepository改成持有连接池:
type OrgRepository struct { pool *pgx.Pool } // 初始化仓库 func NewOrgRepository(pool *pgx.Pool) *OrgRepository { return &OrgRepository{pool: pool} }
非事务场景的使用
直接用连接池生成Queries执行单步操作:
func (r *OrgRepository) GetOrg(ctx context.Context, orgID int64) (*query.Org, error) { q := query.New(r.pool) return q.GetOrg(ctx, orgID) }
事务场景的使用
通过连接池开启事务,生成绑定事务的Queries,执行多步操作后提交或回滚:
func (r *OrgRepository) CreateOrgWithTx(ctx context.Context, orgName string, ownerID int64) error { // 开启事务 tx, err := r.pool.Begin(ctx) if err != nil { return err } defer func() { if err != nil { _ = tx.Rollback(ctx) return } err = tx.Commit(ctx) }() // 生成绑定事务的Queries实例 q := query.New(tx).WithTx(tx) // 也可以直接用query.New(tx),tx已实现DBTX,WithTx仅替换内部db为tx,效果一致 // 执行事务内的第一个操作 orgID, err := q.CreateOrg(ctx, query.CreateOrgParams{ Name: orgName, OwnerID: ownerID, }) if err != nil { return err } // 执行事务内的第二个操作 _, err = q.CreateOrgMember(ctx, query.CreateOrgMemberParams{ OrgID: orgID, UserID: ownerID, }) if err != nil { return err } return err }
关键注意点
- 事务操作中,所有需要在同一事务内执行的SQL操作,都必须使用绑定了当前事务的
Queries实例 - 务必处理好事务的提交和回滚逻辑,建议用
defer确保出错时能自动回滚事务
内容的提问来源于stack exchange,提问作者0xgotznit
相关产品推荐
相关产品推荐

