为什么我会在spring Context之外关闭会话

时间:2016-10-13 15:58:34

标签: java spring hibernate session

我正在尝试使用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 {

}

3 个答案:

答案 0 :(得分:1)

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

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

thread上下文表示当前线程。默认值为jta上下文表示已存在的jta事务 由于此会话对象(使用getCurrentSession()获取)属于hibernate上下文,因此我们不需要关闭它。关闭SessionFactory后,此会话对象将关闭。

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

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

有关线程安全和Hibernate Session&amp; amp;的详细信息。请参阅this.

答案 1 :(得分:1)

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

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

要使用SessionFactory.getCurrentSession(),请确保您的调用位于@Transactional方法内,否则它将无法工作,您必须使用openSession()手动打开会话

答案 2 :(得分:1)

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

    </bean>
和@Transational和@Autowired一样,没关系

如果您没有配置事务,则只能使用openSession(),并在想要完成会话时添加closeSession