java org.hibernate.SessionException 有问题:会话已关闭!在休眠中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2398446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 20:57:36  来源:igfitidea点击:

Having an issue with org.hibernate.SessionException: Session is closed! in Hibernate

javahibernatesessionorm

提问by

I've done quite a bit a research on this with no luck, but all the answers have a tendency to point toward the session context settings in the config file. What is odd is that I get a session connection the very first time I hit the page (and therefore, a successful result set), but then when I reload I get the following exception: org.hibernate.SessionException: Session is closed!

我对此做了很多研究,但没有运气,但所有答案都倾向于指向配置文件中的会话上下文设置。奇怪的是,我在第一次点击页面时就获得了一个会话连接(因此,一个成功的结果集),但是当我重新加载时,我得到以下异常:org.hibernate.SessionException: Session is closed!

Here are my config settings that are not DB connection string related:

以下是与数据库连接字符串无关的我的配置设置:

<property name="hibernate.show_sql">false</property>
<property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>        
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="hibernate.cache.use_query_cache">false</property>
<property name="hibernate.cache.use_minimal_puts">false</property>

Here is an example of a call I make that produces the situation I described above.

这是我进行的一个调用示例,它产生了我上面描述的情况。

public T get(int id) {
    session.beginTransaction();
    T type;
    try {
        type = getTypeClass().cast(session.get(getTypeClass(), id));
    } catch (ClassCastException classCastException) {
        throw new ClassCastException(classCastException.getMessage());
    }
    session.getTransaction().commit();
    return type;
}

The session variable reference is to a static field that contains the current session. All of the session connection details are textbook reference manual. For example, here is my Hibernate session utility:

会话变量引用指向包含当前会话的静态字段。所有会话连接的详细信息都是教科书参考手册。例如,这是我的 Hibernate 会话实用程序:

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateSessionFactoryUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

采纳答案by Pascal Thivent

When you get a Session with sessionFactory.getCurrentSession(), the Session is flushed and closed automatically when the transaction is commited (see Sessions and transactionsfor more details on this). So, here I suspect that 1. you get the Session once for all (this would explain why the first call works and why subsequent calls fail) which is wrong and 2. you seem to use the session-per-operationanti-pattern which is even worse.

当您使用 Session 时sessionFactory.getCurrentSession(),Session 会在事务提交时自动刷新并关闭(有关更多详细信息,请参阅会话和事务)。所以,在这里我怀疑 1. 你一次获得了 Session(这将解释为什么第一次调用有效以及为什么后续调用失败)这是错误的 2. 你似乎使用了session-per-operation反模式更糟。

In a web application, you should use a session-per-requeststrategy which means that "a single Session and a single database transaction implement the processing of a particular request event". Again, refer to the Sessions and transactionsdocument.

在 Web 应用程序中,您应该使用session-per-request策略,这意味着“单个 Session 和单个数据库事务实现对特定请求事件的处理”。再次参考 会话和交易文档。

And if you want to remove transaction demarcation from your data access code, then you could use an interceptorto start a database transaction at the begin of each request and commit it at the end of the request. Have a look at the Open Session in Viewfor an implementation of this pattern (with a sample DAO demonstrating the benefits).

如果您想从数据访问代码中删除事务划分,那么您可以使用拦截器在每个请求开始时启动数据库事务,并在请求结束时提交它。查看视图中的Open Session 以了解此模式的实现(使用示例 DAO 演示好处)。