跨Repository事务场景下两种DB连接传递方案哪种更优?
两种方案对比结论
第一种显式传递数据库连接/事务的方案更优,理由如下:
- 类型安全有保障:第二种通过context传值的方案属于运行时动态取值,没有编译期类型校验,很容易出现key拼写错误、类型转换失败、值为空等问题,排查成本很高。
- 代码可读性更强:从函数签名就能直接看出repository方法依赖数据库连接,不需要额外阅读内部实现,也不需要团队额外约定统一的context存储key,避免不同模块key命名冲突。
- 可测试性更好:单测时可以直接把mock的数据库连接/事务对象传入方法,不需要额外构造携带指定值的context,测试代码更简洁。
优化建议
你可以额外抽象一个公共的DBExecutor接口,把原生数据库连接和事务对象共有的Query、Exec、QueryRow等方法都封装到这个接口里,repository的方法参数直接接收这个接口类型即可,这样同一个方法既支持传入普通连接执行单操作,也支持传入事务对象执行跨库操作,不需要写两套逻辑。
示例代码:
type DBExecutor interface { QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row } // repository方法示例 func (r *RepositoryOne) Get(ctx context.Context, db DBExecutor) (Model, error) { // 内部逻辑直接用db执行操作即可 }
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

