首先,我提供的数据点很少 接下来将是所描述的问题。
数据点
[D1] 在Hibernate
以及Annotation
和managed objects
世界中,我看到的是像
@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 doc说(link):
多用户客户端/服务器应用程序中最常见的模式是每个请求的会话。
[D2] 还建议使用连接池库C3P0
来汇集与数据库的连接,如postgres文档(link)中所述:
Pg通常会一次完成相同的10,000次交易,一次完成5次,10次或20次,而不是一次完成500次。
[D3] 还有JDBC
给定一个连接,我们可以一次运行一个事务,并在该事务中尽可能多地声明。
它取决于应用程序(C3P0),以确保执行两个不同事务方法的两个不同线程不应使用相同的连接,并且应该在调用另一个方法之前等待。
问题:
现在,如果我们使用带有hibernate和session-per-request的注释以及连接池(仅用1个连接)来使用托管bean事务模式
还要说代码就像
@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(...)
将执行只读查询,两个线程都可以使用相同的连接,并且不执行查询执行查询。
在上面的例子中,我们保持该连接空闲并保持线程等待。
主要问题
有没有办法说hibernate特定的hibernate事务是只读的,然后hibernate可以重用已经获得的连接而不是从连接池请求新的连接?
找到/建议的解决方案很少:(没有说服力)
1如果你非常担心,不要使用注释使用事务,请自己使用hibernate会话.....不,我喜欢那种模式:)
2 Hibernate提供了ConnectionRelease
link选项,可以设置为after_statement
。
第一个 Hibernate C3P0连接池提供程序不支持after_statement
第二个它将是一个开销,只需释放并重新获取连接。
答案 0 :(得分:0)
您不能将来自不同线程的事务多路复用到一个JDBC连接。即使JTA规范说这可能是可能的,但事实上,这并没有发生,并且JDBC驱动程序是同步的。
1)和2)以及适合您需求的正确建议。
after_statement
incurs some penalty,但它仍将事务绑定到连接。因此,可行的替代方案是: