[原創(chuàng)]Hibernate過濾器
最近在項目中使用了Struts + Hibernate的組合,在session和事務(wù)管理上遇到了些問題,查閱了一些資料后,決定采用servlet的過濾器來解決管理問題。
主要修改了HibernateSessionFactory.java(由原文件由myeclipse自動生成的)
在myec生成的HibernateSessionFactory源代碼中,保證了在一次請求過程中共享單一的session實例,我們現(xiàn)在要加入的內(nèi)容就是在一次請求中共享一個Transaction實例,很明顯,中文部分是增加的內(nèi)容。添加的代碼封裝了事務(wù)的開始,提交以及回滾。這樣子session和Transaction實例可以跨越一次請求的多種方法,這有助于實現(xiàn)集合的延遲加載等Hibernate特性。
在用的時候,我們就應(yīng)該使用封裝后的事務(wù)方法和session方法,使用方法如下:
在我們的項目中,BaseDAO類封裝了Hibernate常用的數(shù)據(jù)庫操作方法,其中HibernateSessionFactory.beginTransaction()已經(jīng)一起封入了BaseDAO類,于是,我們便不用在使用代碼中加入事務(wù)開始的方法,直接調(diào)用BaseDAO類的方法即可。在調(diào)試過程中,如果我們需要測試數(shù)據(jù)是否能夠?qū)懭霐?shù)據(jù)庫,就應(yīng)該手工調(diào)用事務(wù)結(jié)束方法HibernateSessionFactory.commitTransaction(),即可立即寫入數(shù)據(jù)庫。
注意:在一次業(yè)務(wù)邏輯中,只能用一次事務(wù)提交,也只需要一次事務(wù)提交,我們一般把事務(wù)提交放到語句執(zhí)行的最后面。(如果你用了多次提交,只對第一次提交有效!)
下面舉例:
但在實際的應(yīng)用中,我們應(yīng)該把測試用的手工代碼刪除,因為事務(wù)和session的關(guān)閉還有事務(wù)的回滾是通過過濾器來完成的,當(dāng)然過濾器需要servlet的支持,我們先來看看過濾器的代碼:
相應(yīng)的web.xml配置:
需要注意的是多個過濾器之間的順序位置,filterChain.doFilter(request,?response);是指調(diào)用下一個過濾器,也就是說,要調(diào)用完所有過濾器后,才會繼續(xù)運行filterChain.doFilter(request,?response);下面的內(nèi)容,這是一個遞歸的過程。所以,在web.xml的配置中,我們要把Hibernate過濾器放在第一位,確保所有servlet運行完畢后,才調(diào)用最后的關(guān)閉方法。
主要修改了HibernateSessionFactory.java(由原文件由myeclipse自動生成的)
public?class?HibernateSessionFactory?{
????/**
?????*?Location?of?hibernate.cfg.xml?file.?Location?should?be?on?the?classpath
?????*?as?Hibernate?uses?#resourceAsStream?style?lookup?for?its?configuration
?????*?file.?The?default?classpath?location?of?the?hibernate?config?file?is?in
?????*?the?default?package.?Use?#setConfigFile()?to?update?the?location?of?the
?????*?configuration?file?for?the?current?session.
?????*/
????private?static?String?CONFIG_FILE_LOCATION?=?"/hibernate.cfg.xml";
????private?static?final?ThreadLocal<Session>?threadLocal?=?new?ThreadLocal<Session>();
????private?static?final?ThreadLocal<Transaction>?tLocaltx?=?new?ThreadLocal<Transaction>();
????private?static?Configuration?configuration?=?new?Configuration();
????private?static?org.hibernate.SessionFactory?sessionFactory;
????private?static?String?configFile?=?CONFIG_FILE_LOCATION;
????private?HibernateSessionFactory()?{
????}
????/**
?????*?Returns?the?ThreadLocal?Session?instance.?Lazy?initialize?the
?????*?<code>SessionFactory</code>?if?needed.
?????*?
?????*?@return?Session
?????*?@throws?HibernateException
?????*/
????public?static?Session?getSession()?throws?HibernateException?{
????????Session?session?=?(Session)?threadLocal.get();
????????if?(session?==?null?||?!session.isOpen())?{
????????????if?(sessionFactory?==?null)?{
????????????????rebuildSessionFactory();
????????????}
????????????session?=?(sessionFactory?!=?null)???sessionFactory.openSession()?:?null;
????????????threadLocal.set(session);
????????}
????????return?session;
????}
????/**
?????*?Rebuild?hibernate?session?factory
?????*?
?????*/
????public?static?void?rebuildSessionFactory()?{
????????try?{
????????????configuration.configure(configFile);
????????????sessionFactory?=?configuration.buildSessionFactory();
????????}?catch?(Exception?e)?{
????????????System.err.println("%%%%?Error?Creating?SessionFactory?%%%%");
????????????e.printStackTrace();
????????}
????}
????/**
?????*?Close?the?single?hibernate?session?instance.
?????*?
?????*?@throws?HibernateException
?????*/
????public?static?void?closeSession()?throws?HibernateException?{
????????Session?session?=?(Session)?threadLocal.get();
????????threadLocal.set(null);
????????if?(session?!=?null)?{
????????????session.close();
????????}
????}
????/**
?????*?return?session?factory
?????*?
?????*/
????public?static?org.hibernate.SessionFactory?getSessionFactory()?{
????????return?sessionFactory;
????}
????/**
?????*?return?session?factory
?????*?
?????*?session?factory?will?be?rebuilded?in?the?next?call
?????*/
????public?static?void?setConfigFile(String?configFile)?{
????????HibernateSessionFactory.configFile?=?configFile;
????????sessionFactory?=?null;
????}
????/**
?????*?return?hibernate?configuration
?????*?
?????*/
????public?static?Configuration?getConfiguration()?{
????????return?configuration;
????}
????/**
?????*?打開一個事務(wù)
?????*/
????public?static?void?beginTransaction()?{
????????Transaction?tx?=?tLocaltx.get();
????????try?{
????????????if?(tx?==?null)?{
????????????????tx?=?getSession().beginTransaction();
????????????????tLocaltx.set(tx);
????????????}
????????}?catch?(Exception?e)?{
????????????System.err.println("%%%%?Error?beginTransaction?%%%%");
????????????e.printStackTrace();
????????}
????}
????/**
?????*?關(guān)閉一個事務(wù)
?????*/
????public?static?void?commitTransaction()?{
????????Transaction?tx?=?tLocaltx.get();
????????try?{
????????????if?(tx?!=?null?&&?!tx.wasCommitted()?&&?!tx.wasRolledBack())?{
????????????????tx.commit();
????????????????//一個事務(wù)結(jié)束就立即解除與tLocaltx的關(guān)聯(lián)
????????????????tLocaltx.set(null);
????????????}
????????}?catch?(Exception?e)?{
????????????System.err.println("%%%%?Error?commitTransaction?%%%%");
????????????e.printStackTrace();
????????}
????}
????
????/**
?????*?事務(wù)回滾
?????*/
????public?static?void?rollbackTransaction()?{
????????Transaction?tx?=?tLocaltx.get();
????????try?{
????????????tLocaltx.set(null);
????????????if?(tx?!=?null?&&?!tx.wasCommitted()?&&?!tx.wasRolledBack())?
????????????????tx.rollback();
????????}?catch?(Exception?e)?{
????????????System.err.println("%%%%?Error?rollbackTransaction?%%%%");
????????????e.printStackTrace();
????????}
????}
}
????/**
?????*?Location?of?hibernate.cfg.xml?file.?Location?should?be?on?the?classpath
?????*?as?Hibernate?uses?#resourceAsStream?style?lookup?for?its?configuration
?????*?file.?The?default?classpath?location?of?the?hibernate?config?file?is?in
?????*?the?default?package.?Use?#setConfigFile()?to?update?the?location?of?the
?????*?configuration?file?for?the?current?session.
?????*/
????private?static?String?CONFIG_FILE_LOCATION?=?"/hibernate.cfg.xml";
????private?static?final?ThreadLocal<Session>?threadLocal?=?new?ThreadLocal<Session>();
????private?static?final?ThreadLocal<Transaction>?tLocaltx?=?new?ThreadLocal<Transaction>();
????private?static?Configuration?configuration?=?new?Configuration();
????private?static?org.hibernate.SessionFactory?sessionFactory;
????private?static?String?configFile?=?CONFIG_FILE_LOCATION;
????private?HibernateSessionFactory()?{
????}
????/**
?????*?Returns?the?ThreadLocal?Session?instance.?Lazy?initialize?the
?????*?<code>SessionFactory</code>?if?needed.
?????*?
?????*?@return?Session
?????*?@throws?HibernateException
?????*/
????public?static?Session?getSession()?throws?HibernateException?{
????????Session?session?=?(Session)?threadLocal.get();
????????if?(session?==?null?||?!session.isOpen())?{
????????????if?(sessionFactory?==?null)?{
????????????????rebuildSessionFactory();
????????????}
????????????session?=?(sessionFactory?!=?null)???sessionFactory.openSession()?:?null;
????????????threadLocal.set(session);
????????}
????????return?session;
????}
????/**
?????*?Rebuild?hibernate?session?factory
?????*?
?????*/
????public?static?void?rebuildSessionFactory()?{
????????try?{
????????????configuration.configure(configFile);
????????????sessionFactory?=?configuration.buildSessionFactory();
????????}?catch?(Exception?e)?{
????????????System.err.println("%%%%?Error?Creating?SessionFactory?%%%%");
????????????e.printStackTrace();
????????}
????}
????/**
?????*?Close?the?single?hibernate?session?instance.
?????*?
?????*?@throws?HibernateException
?????*/
????public?static?void?closeSession()?throws?HibernateException?{
????????Session?session?=?(Session)?threadLocal.get();
????????threadLocal.set(null);
????????if?(session?!=?null)?{
????????????session.close();
????????}
????}
????/**
?????*?return?session?factory
?????*?
?????*/
????public?static?org.hibernate.SessionFactory?getSessionFactory()?{
????????return?sessionFactory;
????}
????/**
?????*?return?session?factory
?????*?
?????*?session?factory?will?be?rebuilded?in?the?next?call
?????*/
????public?static?void?setConfigFile(String?configFile)?{
????????HibernateSessionFactory.configFile?=?configFile;
????????sessionFactory?=?null;
????}
????/**
?????*?return?hibernate?configuration
?????*?
?????*/
????public?static?Configuration?getConfiguration()?{
????????return?configuration;
????}
????/**
?????*?打開一個事務(wù)
?????*/
????public?static?void?beginTransaction()?{
????????Transaction?tx?=?tLocaltx.get();
????????try?{
????????????if?(tx?==?null)?{
????????????????tx?=?getSession().beginTransaction();
????????????????tLocaltx.set(tx);
????????????}
????????}?catch?(Exception?e)?{
????????????System.err.println("%%%%?Error?beginTransaction?%%%%");
????????????e.printStackTrace();
????????}
????}
????/**
?????*?關(guān)閉一個事務(wù)
?????*/
????public?static?void?commitTransaction()?{
????????Transaction?tx?=?tLocaltx.get();
????????try?{
????????????if?(tx?!=?null?&&?!tx.wasCommitted()?&&?!tx.wasRolledBack())?{
????????????????tx.commit();
????????????????//一個事務(wù)結(jié)束就立即解除與tLocaltx的關(guān)聯(lián)
????????????????tLocaltx.set(null);
????????????}
????????}?catch?(Exception?e)?{
????????????System.err.println("%%%%?Error?commitTransaction?%%%%");
????????????e.printStackTrace();
????????}
????}
????
????/**
?????*?事務(wù)回滾
?????*/
????public?static?void?rollbackTransaction()?{
????????Transaction?tx?=?tLocaltx.get();
????????try?{
????????????tLocaltx.set(null);
????????????if?(tx?!=?null?&&?!tx.wasCommitted()?&&?!tx.wasRolledBack())?
????????????????tx.rollback();
????????}?catch?(Exception?e)?{
????????????System.err.println("%%%%?Error?rollbackTransaction?%%%%");
????????????e.printStackTrace();
????????}
????}
}
在myec生成的HibernateSessionFactory源代碼中,保證了在一次請求過程中共享單一的session實例,我們現(xiàn)在要加入的內(nèi)容就是在一次請求中共享一個Transaction實例,很明顯,中文部分是增加的內(nèi)容。添加的代碼封裝了事務(wù)的開始,提交以及回滾。這樣子session和Transaction實例可以跨越一次請求的多種方法,這有助于實現(xiàn)集合的延遲加載等Hibernate特性。
在用的時候,我們就應(yīng)該使用封裝后的事務(wù)方法和session方法,使用方法如下:
//獲得唯一的session?實例
Session?session?=?HibernateSessionFactory.getSession();
HibernateSessionFactory.beginTransaction();
//do something……(數(shù)據(jù)庫操作如:添加、刪除等)
HibernateSessionFactory.commitTransaction();
Session?session?=?HibernateSessionFactory.getSession();
HibernateSessionFactory.beginTransaction();
//do something……(數(shù)據(jù)庫操作如:添加、刪除等)
HibernateSessionFactory.commitTransaction();
在我們的項目中,BaseDAO類封裝了Hibernate常用的數(shù)據(jù)庫操作方法,其中HibernateSessionFactory.beginTransaction()已經(jīng)一起封入了BaseDAO類,于是,我們便不用在使用代碼中加入事務(wù)開始的方法,直接調(diào)用BaseDAO類的方法即可。在調(diào)試過程中,如果我們需要測試數(shù)據(jù)是否能夠?qū)懭霐?shù)據(jù)庫,就應(yīng)該手工調(diào)用事務(wù)結(jié)束方法HibernateSessionFactory.commitTransaction(),即可立即寫入數(shù)據(jù)庫。
注意:在一次業(yè)務(wù)邏輯中,只能用一次事務(wù)提交,也只需要一次事務(wù)提交,我們一般把事務(wù)提交放到語句執(zhí)行的最后面。(如果你用了多次提交,只對第一次提交有效!)
下面舉例:
//testDAO?繼承?BaseDAO?
public?class testDAO?extends?BaseDAO?{
??? testDAO(){
????????super();
????}
}
public?class testDAO?extends?BaseDAO?{
??? testDAO(){
????????super();
????}
}
public?class?testAction {
????public?static?void?main(String[]?args)?{
????????ActionDAO?ad?=?new?ActionDAO();
????????ad.add(object);
????????//?手工調(diào)用事務(wù)提交,可將緩存中的數(shù)據(jù)立即寫入數(shù)據(jù)庫
????????HibernateSessionFactory.commitTransaction();
????????//?手工調(diào)用session關(guān)閉
????????HibernateSessionFactory.closeSession();
????}
}
????public?static?void?main(String[]?args)?{
????????ActionDAO?ad?=?new?ActionDAO();
????????ad.add(object);
????????//?手工調(diào)用事務(wù)提交,可將緩存中的數(shù)據(jù)立即寫入數(shù)據(jù)庫
????????HibernateSessionFactory.commitTransaction();
????????//?手工調(diào)用session關(guān)閉
????????HibernateSessionFactory.closeSession();
????}
}
但在實際的應(yīng)用中,我們應(yīng)該把測試用的手工代碼刪除,因為事務(wù)和session的關(guān)閉還有事務(wù)的回滾是通過過濾器來完成的,當(dāng)然過濾器需要servlet的支持,我們先來看看過濾器的代碼:
public?class?CloseSessionFilter?extends?HttpServlet?implements?Filter?{
????/**
?????*?
?????*/
????private?static?final?long?serialVersionUID?=?1L;
????private?FilterConfig?filterConfig;
????protected?boolean?enable;?//?是否起用此過濾器
????public?void?init(FilterConfig?filterConfig)?throws?ServletException?{
????????this.filterConfig?=?filterConfig;
????????loadConfigParams();
????}
????public?void?loadConfigParams()?{?//?取得初始化參數(shù)
????????String?enableStr?=?this.filterConfig.getInitParameter("enable");
????????if?(enableStr.trim().equals("true"))?{
????????????this.enable?=?true;
????????}?else?{
????????????this.enable?=?false;
????????}
????}
????//?Process?the?request/response?pair
????public?void?doFilter(ServletRequest?request,?ServletResponse?response,?FilterChain?filterChain)?{
????????try?{
????????????filterChain.doFilter(request,?response);
????????}?catch?(Exception?sx)?{
????????}?finally?{
????????????if?(enable)?{
????????????????try?{
????????????????????HibernateSessionFactory.commitTransaction();
????????????????}?catch?(Exception?e)?{
????????????????????HibernateSessionFactory.rollbackTransaction();
????????????????}?finally?{
????????????????????HibernateSessionFactory.closeSession();
????????????????}
????????????}
????????}
????}
????//?Clean?up?resources
????public?void?destroy()?{
????}
}
????/**
?????*?
?????*/
????private?static?final?long?serialVersionUID?=?1L;
????private?FilterConfig?filterConfig;
????protected?boolean?enable;?//?是否起用此過濾器
????public?void?init(FilterConfig?filterConfig)?throws?ServletException?{
????????this.filterConfig?=?filterConfig;
????????loadConfigParams();
????}
????public?void?loadConfigParams()?{?//?取得初始化參數(shù)
????????String?enableStr?=?this.filterConfig.getInitParameter("enable");
????????if?(enableStr.trim().equals("true"))?{
????????????this.enable?=?true;
????????}?else?{
????????????this.enable?=?false;
????????}
????}
????//?Process?the?request/response?pair
????public?void?doFilter(ServletRequest?request,?ServletResponse?response,?FilterChain?filterChain)?{
????????try?{
????????????filterChain.doFilter(request,?response);
????????}?catch?(Exception?sx)?{
????????}?finally?{
????????????if?(enable)?{
????????????????try?{
????????????????????HibernateSessionFactory.commitTransaction();
????????????????}?catch?(Exception?e)?{
????????????????????HibernateSessionFactory.rollbackTransaction();
????????????????}?finally?{
????????????????????HibernateSessionFactory.closeSession();
????????????????}
????????????}
????????}
????}
????//?Clean?up?resources
????public?void?destroy()?{
????}
}
相應(yīng)的web.xml配置:
????<!--?過濾器?settings:?-->
????<filter>
????????<filter-name>CloseSessionFilter</filter-name>
????????<filter-class>
????????????com.struts.common.CloseSessionFilter
????????</filter-class>
????????<init-param>
????????????<param-name>enable</param-name>
????????????<param-value>true</param-value>
????????</init-param>
????</filter>
????
????<filter-mapping>
????????<filter-name>CloseSessionFilter</filter-name>
????????<servlet-name>action</servlet-name>
????</filter-mapping>
????<filter>
????????<filter-name>CloseSessionFilter</filter-name>
????????<filter-class>
????????????com.struts.common.CloseSessionFilter
????????</filter-class>
????????<init-param>
????????????<param-name>enable</param-name>
????????????<param-value>true</param-value>
????????</init-param>
????</filter>
????
????<filter-mapping>
????????<filter-name>CloseSessionFilter</filter-name>
????????<servlet-name>action</servlet-name>
????</filter-mapping>
需要注意的是多個過濾器之間的順序位置,filterChain.doFilter(request,?response);是指調(diào)用下一個過濾器,也就是說,要調(diào)用完所有過濾器后,才會繼續(xù)運行filterChain.doFilter(request,?response);下面的內(nèi)容,這是一個遞歸的過程。所以,在web.xml的配置中,我們要把Hibernate過濾器放在第一位,確保所有servlet運行完畢后,才調(diào)用最后的關(guān)閉方法。
posted on 2007-08-04 18:30 藍色幽默 閱讀(698) 評論(0) 編輯 收藏 所屬分類: Hibernate