共享数据库连接

huangapple go评论81阅读模式
英文:

Share db connection

问题

首先,我阅读了这篇文章:https://www.alexedwards.net/blog/organising-database-access

基本上,几乎所有的文章都假设将数据库连接存储在存储库结构中。

但是假设有这种情况:
我们有2个存储库
还有一些句柄。
在这个句柄中,我们必须从第一个存储库中读取一些模型。
然后创建另一个模型并插入到第二个存储库中。
而且我们必须在事务中进行操作。

如果我们在每个存储库中存储数据库连接:
在第一个存储库中,我们开始事务,然后我们无法在第二个存储库中使用该事务。

我考虑了以下解决方案:
1.

func (self *handles) SomeHandle(ctx context.Context) {
   dbConnection := self.acquireConnectionFromPool();
   dbConnection.beginTransaction();
   // 跳过错误检查
   model := self.repositoryOne.get(dbConnection);
   // 创建新模型
   self.repositoryTwo.save(dbConnection, newModel);
   dbConnection.commit();
}
func (self *handles) SomeHandle(ctx context.Context) {
   dbConnection := self.acquireConnectionFromPool();
   dbConnection.beginTransaction();
   ctxDb := context.WithValue(ctx, "db", dbConnection)
   // 跳过错误检查
   model := self.repositoryOne.get(ctxDb);
   // 创建新模型
   self.repositoryTwo.save(ctxDb, newModel);
   dbConnection.commit();
}

哪个解决方案更好?

英文:

First of all I read this article:
https://www.alexedwards.net/blog/organising-database-access

Basically almost all articles suppose to store db connection in repository struct.

But suppose there is this case:
We have 2 repositories
Also have some handle.
In this handle we have to read some model from the first repository.
Then create another model and insert in to the second repository.
And we have to do in transaction.

If we store db connection in each repositories:
in the first repository we begin transaction, and then we cannot use this transaction in the second repository.

I thought about these solution:
1.

func (self *handles) SomeHandle(ctx context.Context) {
   dbConnection := self.acquireConnectionFromPool();
   dbConnection.beginTransaction();
   // skip errors checking
   model := self.repositoryOne.get(dbConnection);
   // create new model
   self.repositoryTwo.save(dbConnection, newModel);
   dbConnection.commit();
}

2.

func (self *handles) SomeHandle(ctx context.Context) {
   dbConnection := self.acquireConnectionFromPool();
   dbConnection.beginTransaction();
   ctxDb := context.WithValue(ctx, "db", dbConnection)
   // skip errors checking
   model := self.repositoryOne.get(ctxDb);
   // create new model
   self.repositoryTwo.save(ctxDb, newModel);
   dbConnection.commit();
}

Which solution is better?

答案1

得分: 3

sql.DB不仅仅是与数据库的连接。它通过根据需要创建/池化连接来抽象出连接处理过程,使您无需关心连接的处理。在您的存储库中,可以安全地重用一个sql.DB。这个结论可以从文档中得出:

> SetConnMaxIdleTime设置连接可以空闲的最长时间。

以上定义足以得出结论,sql.DB不是一个连接,而是一个接口,通过抽象驱动程序/连接实现,提供对数据库的通用访问。

英文:

sql.DB is more than a connection to your database. It abstracts away the connection handling from you by creating/pooling connections as needed. It is safe to reuse one sql.DB everywhere in your repositories. This conclusion can be draw from docs where it is stated:

> SetConnMaxIdleTime sets the maximum amount of time a connection may be idle.

The above definition is enough to conclude that sql.DB is not a connection but an interface which provides generic access to the database by abstracting away driver/connection implementation.

huangapple
  • 本文由 发表于 2021年9月2日 04:16:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/69020097.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定