Hibernate一直都認為比較簡單 就那么影射一下:)但最近項目當中遇見很多問題,今天看見別人在項目當中使用了 Hibernate3的DetachedCriteria,感覺真的是太好了,于是就花了點時間研究了一下,希望和大家分享一下吧
            針對這種需求,對于分層應用程序來說,Web層需要傳遞一個查詢的條件列表給業(yè)務層對象,業(yè)務層對象獲得這個條件列表之后,然后依次取出條件,構造查詢語句。這里的一個難點是條件列表用什么來構造?傳統上使用Map,但是這種方式缺陷很大,Map可以傳遞的信息非常有限,只能傳遞name和value,無法傳遞究竟要做怎樣的條件運算,究竟是大于,小于,like,還是其它的什么,業(yè)務層對象必須確切掌握每條entry的隱含條件。因此一旦隱含條件改變,業(yè)務層對象的查詢構造算法必須相應修改,但是這種查詢條件的改變是隱式約定的,而不是程序代碼約束的,因此非常容易出錯。

            DetachedCriteria可以解決這個問題,即在web層,程序員使用DetachedCriteria來構造查詢條件,然后將這個DetachedCriteria作為方法調用參數傳遞給業(yè)務層對象。而業(yè)務層對象獲得DetachedCriteria之后,可以在session范圍內直接構造Criteria,進行查詢。就此,查詢語句的構造完全被搬離到web層實現,而業(yè)務層則只負責完成持久化和查詢的封裝即可,與查詢條件構造完全解耦,非常完美!這恐怕也是以前很多企圖在web層代碼中構造HQL語句的人想實現的夢想吧!

            示例代碼片段如下:

            web層程序構造查詢條件:

            
          Java代碼:
          DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
          detachedCriteria.add(Restrictions.eq("name", "department")).createAlias("employees", "e").add(Restrictions.gt(("e.age"), new Integer(20)));


            Department和Employee是一對多關聯,查詢條件為:

            名稱是“department”開發(fā)部門;
            部門里面的雇員年齡大于20歲;

            業(yè)務層對象使用該條件執(zhí)行查詢:

            java代碼: detachedCriteria.getExecutableCriteria(session).list();

            最大的意義在于,業(yè)務層代碼是固定不變的,所有查詢條件的構造都在web層完成,業(yè)務層只負責在session內執(zhí)行之。這樣代碼就可放之四海而皆準,都無須修改了。

            然而Spring和Hibernate3的DetachedCriteria有不兼容的問題,因此在Spring環(huán)境下面使用Hibernate3需要注意:

            Spring的HibernateTemplate提供了Hibernate的完美封裝,即通過匿名類實現回調,來保證Session的自動資源管理和事務的管理。其中核心方法是:

            java代碼:
          HibernateTemplate.execute(new HibernateCallback() {
           public Object doInHibernate(Session session) throws HibernateException {
            ....
           }
          }

            回調方法提供了session作為參數,有了session,就可以自由的使用Hibernate API編程了。使用了spring的之后,代碼修改如下:

            web層代碼:

            java代碼:
          DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
          detachedCriteria.createAlias("employees", "e").add(Restrictions.eq("name", "department")).add(Restrictions.gt(("e.age"), new Integer(20)));
          departmentManager.findByCriteria(detachedCriteria);

            構造detachedCriteria,作為參數傳遞給departmentManager

            業(yè)務層代碼使用spring,DepartmentManager的findByCriteria如下:

            java代碼:

          public List findByCriteria(final DetachedCriteria detachedCriteria) {
           return (List) getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException {
             Criteria criteria = detachedCriteria.getExecutableCriteria(session);
             return criteria.list();
            }
           });
          }

            實際上也就是:

            java代碼:
          Criteria criteria = detachedCriteria.getExecutableCriteria(session);
          return criteria.list();

            而已

            但是該程序代碼執(zhí)行,會拋出強制類型轉換異常!

            我跟蹤了一下spring和Hibernate源代碼,原因如下:

            spring的HibernateTemplate的execute方法提供的回調接口具有Session作為參數,但是實際上,默認情況下,HibernateTemplate傳遞給回調接口的session并不是org.hibernate.impl.SessionImpl類,而是SessionImpl類的一個Proxy類。之所以替換成為一個Proxy類,HibernateTemplate的注釋說明,Proxy提供了一些額外的功能,包括自動設置Cachable,Transaction的超時時間,Session資源的更積極的關閉等等。

            java代碼:
          private boolean exposeNativeSession = false;
          ...

            execute方法內部:
          Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));

            但是遺憾的是,Hibernate的DetachedCriteria的setExecutableCriteria方法卻要求將session參數強制轉為SessionImpl,但是spring傳過來的卻是一個Proxy類,因此就報錯了。

            java代碼:
          public Criteria getExecutableCriteria(Session session) {
           impl.setSession( (SessionImpl) session ); // 要求SessionImpl,Spring傳遞的是Proxy
           return impl;
          }

            解決方法,禁止Spring的HibernateTemplate傳遞Proxy類,強制要求它傳遞真實的SessionImpl類,即給exexute方法增加一個參數,提供參數為true,如下:

            java代碼:
          public List findByCriteria(final DetachedCriteria detachedCriteria) {
           return (List) getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException {
             Criteria criteria = detachedCriteria.getExecutableCriteria(session);
             return criteria.list();
            }
           }, true);
          }
          posted on 2007-12-22 02:44 LifeNote 閱讀(1509) 評論(4)  編輯  收藏 所屬分類: JavaHibernate
          Comments
          • # re: Hibernate3 的DetachedCriteria 學習
            nanako
            Posted @ 2007-12-22 14:36
            你這樣做出會不會使web層和持久層耦合  回復  更多評論   
          • # re: Hibernate3 的DetachedCriteria 學習
            LifeNote
            Posted @ 2007-12-22 16:17
            是的 只是弄一個例子 看看這個怎么用的   回復  更多評論   
          • # re: Hibernate3 的DetachedCriteria 學習[未登錄]
            netfishx
            Posted @ 2007-12-22 19:52
            這樣用根本就是反模式啊  回復  更多評論   
          • # re: Hibernate3 的DetachedCriteria 學習[未登錄]
            John
            Posted @ 2008-01-03 11:06
            在web layer就用上了hibernate,是強耦合。  回復  更多評論   
           
          主站蜘蛛池模板: 昭平县| 六盘水市| 南阳市| 介休市| 奎屯市| 洛扎县| 洛川县| 新邵县| 新绛县| 竹山县| 清镇市| 新津县| 六枝特区| 勐海县| 绵阳市| 屏山县| 湖南省| 沁源县| 昌平区| 板桥市| 霍城县| 马公市| 阳山县| 梅州市| 通许县| 霍林郭勒市| 益阳市| 涿鹿县| 贞丰县| 交城县| 正定县| 武清区| 左权县| 中牟县| 迭部县| 定远县| 银川市| 余姚市| 龙岩市| 从化市| 应用必备|