控制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议使用明确的事务边界(即显式的beginTransaction
和commit
)。
在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()
。