首页 > 解决方案 > Should a single thread only acquire a single connection from a connection pool?

问题描述

I am using ORMLite (Java) with HikariCP and I have a lot of code that's called asynchronously i.e. CompletableFuture.supplyAsync(Supplier). Inside a Supplier I have various calls to different ORMLite Dao objects inside these tasks. I ran into a deadlock scenario and found that increasing the size of the connection pool seemed to have fixed the issue.

After some research, I found that this is a well-documented problem. Having looked at the information provided here:

"Each thread is waiting for a second database connection, and none would become available since all threads are blocked."

This caught my eye. When looking at the ORMLite source code, I found that for each Dao method called, a connection is acquired. In my case, I am calling multiple Dao methods in each asynchronous task I create via CompletableFuture which brings me to my question.

My understanding is that I should only acquire a single connection in each thread so is there a way to do this with ORMLite? Bearing in mind I have calls to different Dao objects and having done some further research, Dao#callBatchTasks(Callable) caught my eye but I am unsure whether I can have calls to different Dao objects inside the Callable. Or is there a flaw in my logic or something fundamental I am missing in my write-up?

标签: javamultithreadingormlite

解决方案


我发现每调用一个 Dao 方法,都会获取一个连接

如果ORMLite需要去数据库,它需要得到一个连接,对吧?有什么地方做得不对吗?

我的理解是我应该只在每个线程中获取一个连接,那么有没有办法用 ORMLite 做到这一点?

我不认为有什么说一个线程不能打开多个数据库连接。只要在您完成te操作时它们都关闭,那么我认为这很好。如果您正在查询都存在于同一个数据库上的不同 DAO,那么只要您完成了连接,您实际上就可以每次都重用该连接。即,如果您使用打开的连接对结果进行分页,然后在中间查询另一个表,那么这可能会搞砸游标。但是,如果您先执行 a dao1.queryAll(),然后执行 a ,则dao2.queryAll()可以使用相同的连接,因为第一个查询已经完成。

但是如果您使用的是连接池,该池应该在 ORMLite 的 ConnectionSource 的帮助下为您进行连接管理。如果需要,该池应该为您创建一个新连接,否则会重用旧连接。对数据库连接进行限制有点奇怪。

Dao#callBatchTasks(Callable)引起了我的注意,但我不确定是否可以调用 Callable 中的不同 Dao 对象。

你可以调用不同的 dao 对象,只要它们都在同一个数据库上。您实际上可以调用一个连接到不同数据库的 dao,但您无法保证数据库之间的事务。

例如,如果您执行以下操作。

  1. 你打电话dao1.callBatchTasks(callable)
  2. 在您的Callable中,您调用dao2.delete(entity1)which 有效。
  3. 仍然在Callable, 你调用dao2.delete(entity2)which throws。
  4. 事务dao1将被回滚,但entity1仍将被删除。

推荐阅读