【问题标题】:why do Iget closed session outside of spring Context为什么我要在春季上下文之外关闭会话
【发布时间】:2016-10-13 15:58:34
【问题描述】:

我正在尝试使用 hibernate 配置 spring,但我注意到我无法获得的一件事:当我尝试从 Container 获取 Session 对象时。
Bean.getBean(GenericDao.class).getCurrentSession(); 我只能关闭会话。
如果我对 openSession() 方法做同样的事情 - 我会收到有效的会话。
那么接下来的问题是:为什么?我一直在谷歌研究,但没有找到答案。有人知道吗?

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;

@Transactional ( propagation = Propagation.REQUIRED, rollbackFor = { Throwable.class } )
public abstract class GenericDao {

    @Autowired
    protected SessionFactory sessionFactory;

    public Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }

    public Session openSession() {
        return sessionFactory.openSession();
    }

    public void saveOrUpdate(final Serializable object) {
        getCurrentSession().saveOrUpdate(object);
    }

    public void delete(final Serializable object) {
        getCurrentSession().delete(object);
    }

    public void save(final Serializable object) {
        getCurrentSession().save(object);
    }

    public void update(final Serializable object) {
        getCurrentSession().update(object);
    }

    public void merge(final Serializable object) {
        getCurrentSession().merge(object);
    }

    @SuppressWarnings ( "unchecked" )
    public <T> List<T> list(final Class<T> clazz) {
        return getCurrentSession().createCriteria(clazz).list();
    }

    @SuppressWarnings ( "unchecked" )
    public <T> T get(final Class<T> clazz, final Serializable id) {
        return (T) getCurrentSession().get(clazz, id);
    }

}

@Repository
@Primary
class GenericDaoImpl extends GenericDao {

}

【问题讨论】:

    标签: java spring hibernate session


    【解决方案1】:

    1)这是因为,使用getCurrentSession() 方法会返回绑定到上下文的会话。但是为了让它工作,我们需要在hibernate配置文件中配置它,如下所示。

    <property name="hibernate.current_session_context_class">thread</property>
    

    thread 上下文表示当前线程。默认值为jta context 表示已经存在的 jta 事务。
    由于这个会话对象(使用getCurrentSession() 获取)属于休眠上下文,我们不需要关闭它。一旦 SessionFactory 关闭,这个会话对象就会关闭。

    getCurrentSession() 应该用于单线程环境。

    2) openSession() 方法总是打开一个新会话。完成所有数据库操作后,我们应该关闭此会话对象。 我们应该为多线程环境中的每个请求打开一个新会话。

    有关线程安全和 Hibernate Session 及其用法的更多详细信息,请参阅this.

    【讨论】:

    • 你是不是想知道hibernate context是在spring中诞生的,这意味着从getCurrenSession()方法获得的session不可能在spring context之外存活?我理解正确吗?
    • 在您的情况下,休眠上下文由 Spring 管理,并且可以从 getCurrenSession() 方法获取会话,但您需要正确配置 hibernate.current_session_context_class 属性值,因为默认值为“JTA”,即一个已经存在的 jta 事务,它可能会在获取它之前关闭你的会话(会话)。
    • 嗯,情况变得更清楚了...谢谢您的回复,我会检查一下
    【解决方案2】:

    Hibernate 使用当前上下文类的概念来确定与 getCurrentSession() 一起使用的 Session 的范围。在纯 Hibernate 中,这可以是 Session 绑定到线程的线程,其中会话绑定到 JTA UserTransaction 的 jta

    当与 Spring 一起使用时,您不需要指定 hibernate.current_session_context_class 属性,因为 Spring 使用它自己的称为 SpringSessionContext。这使用您正在使用的任何 PlatformTransactionManager 将会话绑定到正在进行的事务

    要使用 SessionFactory.getCurrentSession(),请确保您的调用在 @Transactional 方法中,否则它将不起作用,您必须使用 openSession() 手动打开会话

    【讨论】:

    • 对不起,您能否说得更清楚些,或者您能否给我一个指向您找到此信息的资源的链接。直觉上我明白这是我的问题的答案,但我没有得到前两段的要点
    【解决方案3】:

    @Transactional 负责打开和关闭 sessionFactory,你可以在没有 openSession 的情况下使用 getCurrentSession:
    @SuppressWarnings ( "unchecked" ) public <T> List<T> list(final Class<T> clazz) { return getCurrentSession().createCriteria(clazz).list(); }
    如果您使用@Annotation 或在 .xml 文件中配置事务,如下所示:
    &lt;bean id="sessionFactory" class="..."
    &lt;/bean&gt;

    <tx:annotation-driven proxy-target-class="true" transaction-manager="txManager" /> <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean>
    像你一样使用@Transational 和@Autowired,没关系

    如果不配置事务,只能使用openSession(),想结束会话时加上closeSession

    【讨论】:

      猜你喜欢
      • 2016-08-05
      • 1970-01-01
      • 2016-12-06
      • 2013-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多