【发布时间】:2016-08-23 13:45:52
【问题描述】:
首先,我给出了一些数据点。
接下来将描述问题。
数据点:
[D1]在Hibernate 和Annotation 和managed objects 世界中,我看到了一个常见的模式,例如 p>
@Transactional
public void createStuff(..){
// get entity manager and call persist and other operatation
}
@Transactional
public SomeDtoObject getStuff(..){
// get entity manager and call find and getter to polulate a object to return
}
在托管 bean 中,当我们调用此方法时,会启动并提交 Hibernate 事务。
Hibernate 文档说 (link):
多用户客户端/服务器应用程序中最常见的模式是每请求会话。
[D2] 此外,建议使用连接池库 C3P0 对数据库的连接进行池化,如 postgres 文档 (link) 所述:
Pg 通常一次完成 5、10 或 20 个事务比一次执行 500 个事务更快地完成相同的 10,000 个事务。
[D3] 还可以使用JDBC
给定一个连接,我们可以一次运行一个事务,并在该事务中运行任意多条语句。
由应用程序(C3P0)来确保执行两个不同事务方法的两个不同线程不应该使用相同的连接,并且一个应该在调用另一个方法之前等待。
问题:
现在,如果我们使用带有注解的托管 bean 事务模式以及一个连接池(假设只有 1 个连接),带有休眠和每个请求的会话
还可以说代码类似于
@Transactional
public SomeDtoObject getStuff(..){
// get entity manager and call find and getter to polulate a object to return
SomeEntity se = entityManager.find(someentity, primaryKey);
//create Dtos
// access someEntity to all over this method to create SomeDtoObject that we have to return.
// also may access some file on system to fetch some data is order to populate someDtoObject.
// overall let say the method take 150 milli second to do all its work
}
现在想象有两个不同的线程(T1,T2)调用 getStuff(...)
T1会进入方法,会从连接池中获取jdbc连接。
当T2 到达entityManager.find 时,C3P0 将检查是否没有剩余连接,它将暂停T2,直到T1 完成执行,这将花费大约 150 毫秒。
理想情况下,鉴于getStuff(...) 将执行只读查询,两个线程可以使用相同的连接并且不阻止线程执行查询。
在上述情况下,我们保持该连接空闲并保持线程等待。
主要问题
有没有一种方法可以让休眠让特定休眠事务是只读的,然后休眠可以重用已经获得的连接而不是要求来自连接池的新连接?
找到/建议的解决方案很少:(不令人信服)
1如果你很担心,不要使用注释使用事务,自己使用休眠会话.....不,我喜欢那种模式:)
2休眠提供ConnectionReleaselink可以设置为 after_statement 的选项。
FirstHibernate C3P0 连接池提供程序不支持 after_statement。
Second 这将是一个开销,只是释放和重新获取连接。
【问题讨论】:
-
如果池中只有 1 个以上的连接,您不会有任何问题。这样做有什么意义?
-
以上是为了解释...重点是在资源空闲时使用资源...上面的问题是仍然会在池中提供10个连接
-
不,如果池中有足够的连接,则不会。我真的认为您正在寻找人为问题的解决方案。
-
我认为当您知道您的服务器将在 3 秒的时间内收到 8000 个请求时会遇到问题......但重点是在资源空闲时使用资源跨度>
标签: java multithreading hibernate transactions c3p0