2016-10-13 21 views
0

我想用spring配置spring,並且我注意到一件事情我無法得到:當我嘗試從Container獲取Session對象時。
Bean.getBean(GenericDao.class).getCurrentSession();我只能關閉會議。
如果我將與openSession()方法相同 - 我將收到有效會話。
所以接下來的問題是:爲什麼?我一直在谷歌研究,但沒有找到答案。有人知道嗎?爲什麼在彈簧之外的Iget關閉會話上下文

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 { 

} 

回答

1

1)這是因爲,使用getCurrentSession()方法返回綁定到上下文會話。但爲了這個工作,我們需要在休眠配置文件中配置它,如下所示。

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

thread上下文表示當前線程。默認值爲jta上下文表示已經存在的jta事務。
由於此會話對象(使用getCurrentSession()提取)屬於hibernate上下文,因此我們不需要關閉它。 SessionFactory關閉後,會話對象被關閉。

getCurrentSession()應該用於單線程環境。

2)openSession()方法總是打開一個新的會話。一旦我們完成了所有的數據庫操作,我們應該關閉這個會話對象。 我們應該在多線程環境中爲每個請求打開一個新的會話。

對於線程安全和Hibernate的Session &他們使用相關的更多詳細信息,請參閱this.

+0

你是否試圖說,是春天的上下文出生在春天之一,這意味着它不可能從'getCurrenSession()'方法獲得'會話'活着以外的春天上下文嗎?我理解你了嗎? – Dante

+1

在你的情況下,hibernate上下文由Spring管理,並且可以從'getCurrenSession()'方法獲得會話,但是你需要正確配置'hibernate.current_session_context_class'屬性值,因爲默認值是「JTA」即一個已經存在的jta事務,它可以在獲取它之前關閉你的會話(會話)。 –

+0

好吧,情況變得更加清楚了......感謝您的回覆,我會檢查它 – Dante

1

Hibernate使用當前上下文類的概念來確定會議的範圍與的getCurrentSession使用()。在純Hibernate中,這可以是線程,因此會話綁定到線程,jta會話綁定到JTA UserTransaction

與Spring一起使用時,不需要指定hibernate.current_session_context_class屬性,因爲Spring使用自己的調用SpringSessionContext。這使用任何您正在使用的PlatformTransactionManager將會話綁定到正在進行的事務

要使用SessionFactory.getCurrentSession()確保您的調用在@Transactional方法內,否則它不會工作,您必須使用openSession手動打開會話)

+0

我很抱歉,您能更清楚一點,還是您可以給我一個資源鏈接,以便您找到此信息。直覺上我明白這是我的問題的答案,但我沒有得到前兩段的主要觀點 – Dante

1

@Transactional需要開的責任和關閉SessionFactory對象,你可以使用的getCurrentSession不作爲的openSession:
@SuppressWarnings ("unchecked") public <T> List<T> list(final Class<T> clazz) { return getCurrentSession().createCriteria(clazz).list(); }
如果您配置的事務與@annotation或英寸這裏xml文件:
<bean id="sessionFactory" class="..."
</bean>

<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當你想完成會話

相關問題