我是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中的连接一样。那么频繁打开和关闭它是正确的方法吗?
BTW,每次都需要tx.commit()吗?
还有什么是在servlet中使用session的线程问题,因为我看到会话在api中不是线程安全的。
答案 0 :(得分:111)
我是hibernate的新手,在阅读了hibernate api和教程之后,似乎会话在不使用时应该是cloesd。
完成后应该关闭(但我们会看到,这可以自动完成)。
在独立应用程序中使用它时我毫无疑问。但是我不确定何时在网络应用中使用。
嗯,正如文档11.1.1. Unit of work部分所述,多用户客户端/服务器应用程序中的最常见模式是 session-per-请求强> 的
例如,我有一个servlet:TestServlet从客户端接收参数,然后我调用Manager来根据参数查询:就像这样(...)我应该在查询方法中关闭会话?
这完全取决于你如何获得会话。
sessionFactory.getCurrentSession()
,您将获得一个绑定到事务生命周期的“当前会话”,并在事务结束(提交或回滚)时自动刷新和关闭。sessionFactory.openSession()
,则必须自行管理会话并“手动”刷新并关闭它。要实现每个请求的会话模式,请选择第一种方法(更简单,更简洁)。使用第二种方法实现long conversations。
维基页面Sessions and transactions是对此主题文档的很好补充。
BTW,每次都需要tx.commit()吗?
您可能希望阅读Non-transactional data access and the auto-commit mode以澄清一些事情,但简单来说,您的Hibernate代码必须在事务中执行,我建议使用显式事务边界(即显式{{ 1}}和beginTransaction
)。
还有什么是在servlet中使用session的线程问题,因为我看到会话在api中不是线程安全的。
只是不要使它成为Servlet的实例变量,你就不会有任何问题。
答案 1 :(得分:0)
如果您通过sessionFactory.openSession()
进行会话,则必须从外部关闭。非预期的打开会话可能导致数据泄露。此外,它还可以邀请Web App安全威胁。
答案 2 :(得分:0)
我们可以使用public class MyUtil {
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
private static final ThreadLocal<Session> threadLocal;
static {
try {
Configuration configuration = new Configuration();
configuration.configure();
serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
threadLocal = new ThreadLocal<Session>();
} catch(Throwable t){
t.printStackTrace();
throw new ExceptionInInitializerError(t);
}
}
public static Session getSession() {
Session session = threadLocal.get();
if(session == null){
session = sessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
public static void closeSession() {
Session session = threadLocal.get();
if(session != null){
session.close();
threadLocal.set(null);
}
}
public static void closeSessionFactory() {
sessionFactory.close();
StandardServiceRegistryBuilder.destroy(serviceRegistry);
}
}
。
SessionFactory
这里,main
仅使用静态块初始化一次。因此,只要getSession()
类调用threadLocal
,就会首先在closeSession()
对象中检查是否存在Session对象。
因此,该程序提供了线程安全性。
每次操作后,threadLocal
将关闭会话并将closeSessionFactory()
对象设置为null。
最后拨打careers.php
。
答案 3 :(得分:0)
每当第一次调用getCurrentSession()
时,一个会话就会打开,而在事务结束时,会话会关闭。
如果一个会话不存在,则创建一个全新的会话;如果一个会话已经存在,则使用一个现有的会话。它使用自动刷新和自动关闭属性自动配置为true,表示Session
将被自动刷新和关闭。
如果您使用的是getCurrentSession()
,那么如果要尝试使用此方法,则无需关闭连接,那么您将面临异常。