編程生活

             :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            113 隨筆 :: 0 文章 :: 18 評論 :: 0 Trackbacks

          在這,多次提到使用構造型查詢,主要是我不想取出結果后再轉型,這樣,自己也實在太累了,因此,非常希望讓openJPA一下就將結果做好,畢竟感覺上性能也要好過使用簡單查詢方式。

          I.openJPA的構造型查詢


          openJPA在構造型查詢方面好過其它幾家,它支持三種方式:
          1.通過反射注入,通過setXXX(字段名)注入到目標類(dto對象)的字段中
          2.通過put方法,目標類(dto對象)需實現public void put(Object field, Object value)接口方法,然后openJPA的結果包裝器調用此接口,將數據寫到對象中
          3.通過構造方法,目標類(dto對象)提供所需的構造函數,然后openJPA的結果包裝器通過該構造函數實例化.
          第1種方式最好,第3種方式最差,特別是對于查詢結果比較多,做構造函數簡直就是不可能的事
          用第1種方式,雖然最好,但在openJPA0.9.6,0.9.7及1.0.0中對于使用JPQL這種方式均受到限制,缺省情況下openJPA提供的字段名是jpqlalias1,..,而你的DTO對象不可能定義為jpqlalias1,,這樣的字段,這樣就脫離了業務場景,其它開好人員根本不會用.因此,如果構造型查詢的JPQL如果支持別名,這就太好了.我做了以下修改:

          II.修改方案



          1.修改[openjpa-kernel\src\main\jjtree\org\apache\openjpa\kernel\jpql\JPQL.jjt]


          void constructor_parameter() #CONSTRUCTORPARAM : { }
          {
           (path() | aggregate_select_expression() | string_literal() | numeric_literal()) [LOOKAHEAD(1)<AS>] [LOOKAHEAD(identification_variable())identification_variable()]
          }


          2.修改org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.java

          private Expression assignProjections(JPQLNode parametersNode,
                  QueryExpressions exps) 
          {
                  
          int count = parametersNode.getChildCount();
                  exps.projections 
          = new Value[count];
                  exps.projectionClauses 
          = new String[count];
                  exps.projectionAliases 
          = new String[count];

                  Expression exp 
          = null;
                  
                  JPQLNode parentNode 
          = null;
                  JPQLNode itemNode 
          = null;
                  JPQLNode aliasNode 
          = null;
                  String alias 
          = null;

                  
          for (int i = 0; i < count; i++{
                    parentNode 
          = parametersNode.getChild(i);
                    itemNode 
          = firstChild(parentNode);
                    aliasNode 
          = parentNode.children.length == 2 ? right(parentNode) : null;
                    alias 
          = aliasNode == null ? lastChild(itemNode).text : aliasNode.text;
                    exps.projections[i] 
          = getValue(itemNode);
                    exps.projectionAliases[i] 
          = alias == null ? nextAlias() : alias;
                  }

                  
          return exp;
              }



          3.用mvn重新編譯打包,一切ok.

          III.使用示例

          場景:

          /**
          * A實體的一個DTO對象
          */

          public class AData {
              
          private String id;         //標識
              private String type;     //類型
              private String name;    //名稱
              private int cnt;            //子的總數
              
          }


          @Entity
          @Table(..)
          private class A {
              @ID
              @GeneratedValue(generator 
          = "uuid-hex")
              @Column(..)
              
          private String id;
              @Column(..)
              
          private String aName;
              @Column(..)
              
          private String parentID;
              @OneToMany
              @Join..
              
          private List<A> children;
              
          }


          JPQL語法如下:


          select distinct new com.wile.test.AData(a.id, a.aName name, size(a.children) as cnt,'00' type) from A a where a.id=?1

          雖然,我寫的JPQL不太符合規范,但實在是太符合我的要求了.

          posted on 2007-10-26 16:12 wilesun 閱讀(1077) 評論(0)  編輯  收藏 所屬分類: 個人經驗
          主站蜘蛛池模板: 玛纳斯县| 凤凰县| 长治市| 鸡西市| 财经| 灵璧县| 康平县| 茂名市| 济宁市| 瑞昌市| 怀安县| 静海县| 泸定县| 政和县| 华亭县| 瑞昌市| 昭平县| 庄河市| 阆中市| 刚察县| 方正县| 贵南县| 滦平县| 建湖县| 广饶县| 清涧县| 略阳县| 汉阴县| 鹤庆县| 鹤山市| 耒阳市| 盐边县| 焦作市| 灵宝市| 忻州市| 汽车| 浠水县| 微博| 水城县| 伊川县| 大名县|