[原創]Hibernate過濾器
最近在項目中使用了Struts + Hibernate的組合,在session和事務管理上遇到了些問題,查閱了一些資料后,決定采用servlet的過濾器來解決管理問題。
主要修改了HibernateSessionFactory.java(由原文件由myeclipse自動生成的)
在myec生成的HibernateSessionFactory源代碼中,保證了在一次請求過程中共享單一的session實例,我們現在要加入的內容就是在一次請求中共享一個Transaction實例,很明顯,中文部分是增加的內容。添加的代碼封裝了事務的開始,提交以及回滾。這樣子session和Transaction實例可以跨越一次請求的多種方法,這有助于實現集合的延遲加載等Hibernate特性。
在用的時候,我們就應該使用封裝后的事務方法和session方法,使用方法如下:
在我們的項目中,BaseDAO類封裝了Hibernate常用的數據庫操作方法,其中HibernateSessionFactory.beginTransaction()已經一起封入了BaseDAO類,于是,我們便不用在使用代碼中加入事務開始的方法,直接調用BaseDAO類的方法即可。在調試過程中,如果我們需要測試數據是否能夠寫入數據庫,就應該手工調用事務結束方法HibernateSessionFactory.commitTransaction(),即可立即寫入數據庫。
注意:在一次業務邏輯中,只能用一次事務提交,也只需要一次事務提交,我們一般把事務提交放到語句執行的最后面。(如果你用了多次提交,只對第一次提交有效?。?/b>
下面舉例:
但在實際的應用中,我們應該把測試用的手工代碼刪除,因為事務和session的關閉還有事務的回滾是通過過濾器來完成的,當然過濾器需要servlet的支持,我們先來看看過濾器的代碼:
相應的web.xml配置:
需要注意的是多個過濾器之間的順序位置,filterChain.doFilter(request,?response);是指調用下一個過濾器,也就是說,要調用完所有過濾器后,才會繼續運行filterChain.doFilter(request,?response);下面的內容,這是一個遞歸的過程。所以,在web.xml的配置中,我們要把Hibernate過濾器放在第一位,確保所有servlet運行完畢后,才調用最后的關閉方法。
主要修改了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;
????}
????/**
?????*?打開一個事務
?????*/
????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();
????????}
????}
????/**
?????*?關閉一個事務
?????*/
????public?static?void?commitTransaction()?{
????????Transaction?tx?=?tLocaltx.get();
????????try?{
????????????if?(tx?!=?null?&&?!tx.wasCommitted()?&&?!tx.wasRolledBack())?{
????????????????tx.commit();
????????????????//一個事務結束就立即解除與tLocaltx的關聯
????????????????tLocaltx.set(null);
????????????}
????????}?catch?(Exception?e)?{
????????????System.err.println("%%%%?Error?commitTransaction?%%%%");
????????????e.printStackTrace();
????????}
????}
????
????/**
?????*?事務回滾
?????*/
????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;
????}
????/**
?????*?打開一個事務
?????*/
????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();
????????}
????}
????/**
?????*?關閉一個事務
?????*/
????public?static?void?commitTransaction()?{
????????Transaction?tx?=?tLocaltx.get();
????????try?{
????????????if?(tx?!=?null?&&?!tx.wasCommitted()?&&?!tx.wasRolledBack())?{
????????????????tx.commit();
????????????????//一個事務結束就立即解除與tLocaltx的關聯
????????????????tLocaltx.set(null);
????????????}
????????}?catch?(Exception?e)?{
????????????System.err.println("%%%%?Error?commitTransaction?%%%%");
????????????e.printStackTrace();
????????}
????}
????
????/**
?????*?事務回滾
?????*/
????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實例,我們現在要加入的內容就是在一次請求中共享一個Transaction實例,很明顯,中文部分是增加的內容。添加的代碼封裝了事務的開始,提交以及回滾。這樣子session和Transaction實例可以跨越一次請求的多種方法,這有助于實現集合的延遲加載等Hibernate特性。
在用的時候,我們就應該使用封裝后的事務方法和session方法,使用方法如下:
//獲得唯一的session?實例
Session?session?=?HibernateSessionFactory.getSession();
HibernateSessionFactory.beginTransaction();
//do something……(數據庫操作如:添加、刪除等)
HibernateSessionFactory.commitTransaction();
Session?session?=?HibernateSessionFactory.getSession();
HibernateSessionFactory.beginTransaction();
//do something……(數據庫操作如:添加、刪除等)
HibernateSessionFactory.commitTransaction();
在我們的項目中,BaseDAO類封裝了Hibernate常用的數據庫操作方法,其中HibernateSessionFactory.beginTransaction()已經一起封入了BaseDAO類,于是,我們便不用在使用代碼中加入事務開始的方法,直接調用BaseDAO類的方法即可。在調試過程中,如果我們需要測試數據是否能夠寫入數據庫,就應該手工調用事務結束方法HibernateSessionFactory.commitTransaction(),即可立即寫入數據庫。
注意:在一次業務邏輯中,只能用一次事務提交,也只需要一次事務提交,我們一般把事務提交放到語句執行的最后面。(如果你用了多次提交,只對第一次提交有效?。?/b>
下面舉例:
//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);
????????//?手工調用事務提交,可將緩存中的數據立即寫入數據庫
????????HibernateSessionFactory.commitTransaction();
????????//?手工調用session關閉
????????HibernateSessionFactory.closeSession();
????}
}
????public?static?void?main(String[]?args)?{
????????ActionDAO?ad?=?new?ActionDAO();
????????ad.add(object);
????????//?手工調用事務提交,可將緩存中的數據立即寫入數據庫
????????HibernateSessionFactory.commitTransaction();
????????//?手工調用session關閉
????????HibernateSessionFactory.closeSession();
????}
}
但在實際的應用中,我們應該把測試用的手工代碼刪除,因為事務和session的關閉還有事務的回滾是通過過濾器來完成的,當然過濾器需要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()?{?//?取得初始化參數
????????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()?{?//?取得初始化參數
????????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()?{
????}
}
相應的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);是指調用下一個過濾器,也就是說,要調用完所有過濾器后,才會繼續運行filterChain.doFilter(request,?response);下面的內容,這是一個遞歸的過程。所以,在web.xml的配置中,我們要把Hibernate過濾器放在第一位,確保所有servlet運行完畢后,才調用最后的關閉方法。
posted on 2007-08-04 18:30 藍色幽默 閱讀(698) 評論(0) 編輯 收藏 所屬分類: Hibernate