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