J度空間

          [原創]Hibernate過濾器

          最近在項目中使用了Struts + Hibernate的組合,在session和事務管理上遇到了些問題,查閱了一些資料后,決定采用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();
          ????????}
          ????}
          }

          在myec生成的HibernateSessionFactory源代碼中,保證了在一次請求過程中共享單一的session實例,我們現在要加入的內容就是在一次請求中共享一個Transaction實例,很明顯,中文部分是增加的內容。添加的代碼封裝了事務的開始,提交以及回滾。這樣子session和Transaction實例可以跨越一次請求的多種方法,這有助于實現集合的延遲加載等Hibernate特性。

          在用的時候,我們就應該使用封裝后的
          事務方法和session方法,使用方法如下:

          //獲得唯一的session?實例
          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?testAction {
          ????
          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()?{
          ????}
          }

          相應的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>


          需要注意的是多個過濾器之間的順序位置,filterChain.doFilter(request,?response);是指調用下一個過濾器,也就是說,要調用完所有過濾器后,才會繼續運行filterChain.doFilter(request,?response);下面的內容,這是一個遞歸的過程。所以,在web.xml的配置中,我們要把Hibernate過濾器放在第一位,確保所有servlet運行完畢后,才調用最后的關閉方法。


          posted on 2007-08-04 18:30 藍色幽默 閱讀(698) 評論(0)  編輯  收藏 所屬分類: Hibernate

          導航

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          統計

          • 隨筆 - 1
          • 文章 - 22
          • 評論 - 2
          • 引用 - 0

          常用鏈接

          留言簿(4)

          隨筆分類

          文章分類

          相冊

          搜索

          •  

          最新評論

          主站蜘蛛池模板: 临高县| 仲巴县| 两当县| 兴城市| 曲靖市| 佛山市| 杨浦区| 巫溪县| 佛学| 建瓯市| 修水县| 凤山市| 临西县| 五常市| 新田县| 河源市| 日喀则市| 高淳县| 抚宁县| 辽宁省| 望都县| 西贡区| 汕头市| 滨州市| 华安县| 尼玛县| 鹿邑县| 赣榆县| 定日县| 泗阳县| 米林县| 霍州市| 西林县| 玉田县| 庄河市| 绥宁县| 观塘区| 晋城| 新昌县| 定远县| 濮阳县|