我是hibernate的新手,在阅读了hibernate api和教程后,看来会话应该在不使用时关闭 .
像这样:
Session sess=getSession();
Transcration tx=sess.beginTranscration();
//do something using teh session
sess.save(obj);
tx.commit();
sess.close;
在独立应用程序中使用它时我毫无疑问 . 但是我不确定何时在网络应用中使用 .
例如,我有一个servlet: TestServlet
从客户端接收参数,然后我调用Manager来根据参数查询一些东西,就像这样:
class TestServlet{
doGet(HttpServletRequset,httpServletResponse){
String para1=request.getParam...();
String para2=.....
new Manager().query(para1,para2);
}
}
class Manager{
public String query(String pa1,String pa2){
Session=....// get the session
//do query using para1 and 1
session.close() //Here, I wonder if I should close it.
}
}
我应该在查询方法中关闭会话吗?
因为有人告诉我,hibernate中的会话就像jdbc中的连接一样 . 所以经常打开和关闭它是正确的方法吗?
顺便说一句,每次都需要tx.commit()吗?
还有什么是在servlet中使用session的线程问题,因为我看到会话在api中不是线程安全的 .
3 回答
如果您正在通过
sessionFactory.openSession()
进行会话,那么您必须 close it externally . 非预期的打开会话可能导致数据泄露 . 此外,它还可以邀请Web App安全威胁 .我们可以利用
ThreadLocal
.这里,
SessionFactory
仅使用静态块初始化一次 . 因此,只要main
类调用getSession()
,就会首先在threadLocal
对象中检查是否存在Session对象 . 因此,该程序提供了线程安全性 . 每次操作后,closeSession()
将关闭会话并将threadLocal
对象设置为null . 最后拨打closeSessionFactory()
.它应该在你完成后关闭(但这可以自动完成,我们将看到) .
好吧,正如文档的11.1.1. Unit of work部分所述,多用户客户端/服务器应用程序中的 most common 模式是 session-per-request .
这一切都取决于你如何获得会话 .
如果使用
sessionFactory.getCurrentSession()
,您将获得绑定到事务生命周期的"current session",并在事务结束(提交或回滚)时自动刷新和关闭 .如果你决定使用
sessionFactory.openSession()
,你必须自己管理会话并刷新并关闭它"manually" .要实现每个请求的会话模式,首选方法(更容易,更简洁) . 使用第二种方法实现long conversations .
维基页面Sessions and transactions是对该主题文档的很好补充 .
您可能希望阅读Non-transactional data access and the auto-commit mode以澄清一些事情,但简单来说,您的Hibernate代码必须在事务中执行,我建议使用显式事务边界(即显式
beginTransaction
和commit
) .只是不要使它成为Servlet的实例变量,你就不会有任何问题 .
参考文献
Hibernate Core 3.3参考指南
Chapter 11. Transactions and Concurrency
Hibernate wiki
Sessions and transactions
Non-transactional data access and the auto-commit mode