在使用Spring進(jìn)行系統(tǒng)開發(fā)的時(shí)候,數(shù)據(jù)庫連接一般都是配置在Spring的配置文件中,并且由Spring來管理的。在利用Spring + Hibernate進(jìn)行開發(fā)時(shí)也是如此。下面是一個(gè)簡單的Spring + Hibernate Dao的例子:
程序代碼public class DaoReal extends HibernateDaoSupport implements Dao {
public List <User> getAll() {
return super.getHibernateTemplate().find("from User");
}
}
在上面的這個(gè)例子中,我們并沒有關(guān)閉Session,但程序并沒有任何問題,那是因?yàn)镾pring已經(jīng)幫我們關(guān)閉了。那么再看一個(gè)例子:
程序代碼public class DaoReal extends HibernateDaoSupport implements Dao {
public List <User> getAll() {
return super.getSession().createQuery("from User").list();
?。?
}
這個(gè)例子會不會有問題呢?的確,上面的例子中隱藏了一個(gè)問題,數(shù)據(jù)庫連接并沒有被關(guān)閉,在我們的印象中這件事似乎應(yīng)該是Spring的。程序執(zhí)行后,好像也沒有什么問題,但是連續(xù)執(zhí)行該語句n次(n <=最大連接數(shù),如果沒有指定最大連接數(shù),那么默認(rèn)為10次)后,系統(tǒng)處于等待狀態(tài),不會繼續(xù)執(zhí)行了,控制臺上并沒有輸出任何信息。打開log文件,發(fā)現(xiàn)系統(tǒng)拋出java.lang.IllegalStateException: Pool not open的異常,無法打開連接。這說明系統(tǒng)連接池中所有的連接都在使用中。那么我們手動關(guān)閉Session后,應(yīng)該就沒有問題了吧!是這樣嗎?修改我們的例子,如下:
程序代碼public class DaoReal extends HibernateDaoSupport implements Dao {
public List <User> getAll() {
Session s = super.getSession();
try {
return s.createQuery("from User").list();
} finally {
s.close();
}
?。?
}
執(zhí)行n遍后依然停止響應(yīng)。問題出在哪里呢?其實(shí)Spring的Session總是與某個(gè)線程綁定的,而這個(gè)線程往往就是承載Servlet或Jsp的那個(gè)線程,也就是說,它的生命周期scope是request的。在上面的例子中,我們利用getSession強(qiáng)制獲得了Hibernate的Session,這個(gè)Session可能是當(dāng)前事務(wù)中之前使用過的,或者可能是一個(gè)新的,并不在當(dāng)前事務(wù)中,Spring只對當(dāng)前事務(wù)中的Session進(jìn)行關(guān)閉。
要解決這個(gè)問題,方法有很多??梢允褂梦覀冎爸v到過的getHibernateTemplate().find()。也可以設(shè)定HibernateTemplate的AllowCreate為True,并在finally中關(guān)閉Session。也可以將true作為參數(shù)傳遞到super.getSession(..)方法中取得Session。這里的true表示允許創(chuàng)建。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點(diǎn)擊舉報(bào)。