控制hibernate会话(手动closures时)

我是hibernate的新手,在阅读完hibernate api和tutorial后,似乎session不用的时候应该closures。

喜欢这个:

Session sess=getSession(); Transcration tx=sess.beginTranscration(); //do something using teh session sess.save(obj); tx.commit(); sess.close; 

在独立应用程序中使用它时,我毫无疑问。 但是我不确定什么时候在web应用程序中使用。

例如,我有一个Servlet: TestServlet从客户端接收参数,然后我调用pipe理器根据参数来查询某些内容,就像这样:

 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. } } 

我应该closures查询方法中的会话吗?

由于有人告诉我,hibernate中的会话就像jdbc中的连接一样。 那么频繁的打开和closures是正确的方法呢?

顺便说一下,每次都需要tx.commit()吗?

在servlet中使用会话还有什么线程问题,因为我看到会话在api中不是线程安全的。

我在hibernate中是新的,在阅读了hibernate api和tutorial后,似乎会话在不使用的时候应该是cloesd。

当你完成之后它应该被closures(但是我们会看到,这可以自动完成)。

在独立应用程序中使用它时,我毫无疑问。 但是我不确定什么时候在web应用程序中使用。

那么,正如11.1.1节所解释的那样。 文档的工作单元 是多用户客户机/服务器应用程序中最常见的模式,即session-per-request

例如,我有一个Servlet:TestServlet从客户端接收参数,然后我调用一个pipe理器根据参数来查询一些东西:就像这样(…)我应该closures查询方法中的会话吗?

这一切都取决于你如何获得会议。

  • 如果使用sessionFactory.getCurrentSession() ,则将获得绑定到事务生命周期的“当前会话”,并在事务结束(提交或回滚)时自动刷新和closures。
  • 如果您决定使用sessionFactory.openSession() ,则必须自己pipe理会话,并手动刷新和closures会话。

要实现每个请求会话模式,首选方法(更简单,更简单)。 使用第二种方法来实现长对话

维基页面会话和事务是对这个主题的文档的一个很好的补充。

顺便说一下,每次都需要tx.commit()吗?

您可能需要阅读非事务性数据访问和自动提交模式来澄清一些事情,但简单地说,您的Hibernate代码必须在事务中执行,并build议使用明确的事务边界(即显式的beginTransactioncommit )。

在servlet中使用会话还有什么线程问题,因为我看到会话在api中不是线程安全的。

只是不要把它作为Servlet的实例variables,你不会有任何问题。

参考

  • Hibernate Core 3.3参考指南
    • 第11章事务和并发
  • Hibernate维基
    • 会议和交易
    • 非事务性数据访问和自动提交模式

如果您通过sessionFactory.openSession()获取会话,则必须在外部closures会话。 打开的会话意外期间可能导致数据泄漏。 此外,它可以邀请Web应用程序的安全威胁。

我们可以使用ThreadLocal

 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对象中检查Session对象的存在。 因此,这个程序提供了线程安全性。 每次操作之后, closeSession()将closures会话并将threadLocal对象设置为null。 最后调用closeSessionFactory()