为什么我们在应用程序中获得两次当前会话?
最近我做了一些工作来检查在我们的应用程序中在哪里提供与会话相关的代码, 即.获取当前会话(sessionFactory.getCurrentSession());
我在应用程序中看到过这段代码两次,一次是在 HibernateSessionRequestFileter 类
package com.persistence;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.hibernate.StaleObjectStateException;
public class HibernateSessionRequestFilter implements Filter {
private static Log log = LogFactory.getLog(HibernateSessionRequestFilter.class);
private SessionFactory sf;
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
try {
log.debug("Starting a database transaction");
sf.getCurrentSession().beginTransaction();
// Call the next filter (continue request processing)
chain.doFilter(request, response);
// Commit and cleanup
log.debug("Committing the database transaction");
sf.getCurrentSession().getTransaction().commit();
} catch (StaleObjectStateException staleEx) {
log.error("This interceptor does not implement optimistic concurrency control!");
log.error("Your application will not work until you add compensation actions!");
// Rollback, close everything, possibly compensate for any permanent changes
// during the conversation, and finally restart business conversation. Maybe
// give the user of the application a chance to merge some of his work with
// fresh data... what you do here depends on your applications design.
throw staleEx;
} catch (Throwable ex) {
// Rollback only
ex.printStackTrace();
try {
if (sf.getCurrentSession().getTransaction().isActive()) {
log.debug("Trying to rollback database transaction after exception");
//sf.getCurrentSession().getTransaction().rollback();
}
} catch (Throwable rbEx) {
log.error("Could not rollback transaction after exception!", rbEx);
}
// Let others handle it... maybe another interceptor for exceptions?
throw new ServletException(ex);
}
}
public void init(FilterConfig filterConfig) throws ServletException {
log.debug("Initializing filter...");
log.debug("Obtaining SessionFactory from static HibernateUtil singleton");
sf = HibernateUtil.getSessionFactory();
}
public void destroy() {}
}
GenericHibernateDAO 类中的另一个类如下所示,
protected Session getSession() {
if (session == null) {
session = HibernateUtil.getSessionFactory().getCurrentSession();
} else if (!session.isConnected()) {
session = HibernateUtil.getSessionFactory().getCurrentSession();
}
return session;
}
任何人都可以帮助我理解,为什么我们必须在两个地方获取当前会话? 当我们开始事务时,我们将获取 currentsession ,与我们持久化或从数据库获取对象时相同,我们再次获取 currentsession , 为什么会这样呢?
Recently I did some work around to check, where to give the session related code in our application,
ie .Getting current session (sessionFactory.getCurrentSession());
I have seen this code in place twice in the application, one in
HibernateSessionRequestFileter Class
package com.persistence;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.hibernate.StaleObjectStateException;
public class HibernateSessionRequestFilter implements Filter {
private static Log log = LogFactory.getLog(HibernateSessionRequestFilter.class);
private SessionFactory sf;
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
try {
log.debug("Starting a database transaction");
sf.getCurrentSession().beginTransaction();
// Call the next filter (continue request processing)
chain.doFilter(request, response);
// Commit and cleanup
log.debug("Committing the database transaction");
sf.getCurrentSession().getTransaction().commit();
} catch (StaleObjectStateException staleEx) {
log.error("This interceptor does not implement optimistic concurrency control!");
log.error("Your application will not work until you add compensation actions!");
// Rollback, close everything, possibly compensate for any permanent changes
// during the conversation, and finally restart business conversation. Maybe
// give the user of the application a chance to merge some of his work with
// fresh data... what you do here depends on your applications design.
throw staleEx;
} catch (Throwable ex) {
// Rollback only
ex.printStackTrace();
try {
if (sf.getCurrentSession().getTransaction().isActive()) {
log.debug("Trying to rollback database transaction after exception");
//sf.getCurrentSession().getTransaction().rollback();
}
} catch (Throwable rbEx) {
log.error("Could not rollback transaction after exception!", rbEx);
}
// Let others handle it... maybe another interceptor for exceptions?
throw new ServletException(ex);
}
}
public void init(FilterConfig filterConfig) throws ServletException {
log.debug("Initializing filter...");
log.debug("Obtaining SessionFactory from static HibernateUtil singleton");
sf = HibernateUtil.getSessionFactory();
}
public void destroy() {}
}
Another one in GenericHibernateDAO Class Like below,
protected Session getSession() {
if (session == null) {
session = HibernateUtil.getSessionFactory().getCurrentSession();
} else if (!session.isConnected()) {
session = HibernateUtil.getSessionFactory().getCurrentSession();
}
return session;
}
Can anybody help me to understand, why we have to get currentsession in two places?
While we begin the transaction, we are getting the currentsession , same as while we persist or getting object from database, again we are getting the currentsession,
why is it so?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这看起来像 OpenSessionInView 模式的一个版本,其中收到请求时打开 Hibernate 会话并在响应呈现后关闭。
在过滤器中打开会话并启动事务。
然后处理请求并在 Dao 中调用
getCurrentSession()
只获取当前打开的会话,它不会创建新会话。道有它的作用。
然后过滤器提交事务并关闭会话。
This looks like a version of an OpenSessionInView pattern, where a Hibernate Session is opened when a request is received and closed after the response is rendered.
In the filter a session is opened and a transaction is started.
Then the request is processed and in the Dao the call to
getCurrentSession()
only get's the current open session, it isn't creating a new Session.The dao does its work.
Then the filter commits the transaction and the session is closed.