为什么我们在应用程序中获得两次当前会话?

发布于 2024-10-26 08:02:21 字数 3446 浏览 1 评论 0原文

最近我做了一些工作来检查在我们的应用程序中在哪里提供与会话相关的代码, 即.获取当前会话(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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

薔薇婲 2024-11-02 08:02:21

这看起来像 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文