Hibernate綜合查詢解決方案

Hibernate查詢解決方案

      這兩個星期以來,我把原來用struts開發的一個測試工具改用struts+hibernate來實現,首先從心情上來,整個開發過程中始終保持愉快和平和,“原來開發可以這樣愉快?”,再一點就是開發效率上高效了許多。
      現在sun又加入jdocentral.com開始着手JDO2.0,想想看等它出臺以後將是一個怎樣激動人心得場面,讓我們拭目以待。
     
      用Hibernate來操縱持久數據非常簡單,在這裏一些簡單的查詢我會一筆帶過,本文着重說明在綜合查詢兼有分頁的時候我的一些經驗,如果網友覺得我的方案還有不足的地方,也請和我討論,我的email:[email protected].
     
      第一部分:Hibernate提供的查詢接口或其方法(此部分不做深究,請參考hibernate手冊)
     
       1。根據ID查詢
    要用到Session接口的load方法。
    load(Class theClass, Serializable id)
    load(Class theClass, Serializable id, LockMode lockMode)
    load(Object object, Serializable id) 
    
       2。HQL語句進行查詢
      
       2。1 利用Query接口,Query由Session裏的createQuery()來產生一個查詢
        1)不帶參數的查詢(這類比較簡單)
        Query query=session.createQuery("select user from User as user");
        2)帶參數的查詢
        Query query=session.createQuery("select user from User as user where user.name=?");
        query.setString(0,name)//假設name爲傳過來的參數
        Query query=session.createQuery("select user from User as user where user.name=:name");
        query.setString("name",name)//假設name爲傳過來的參數
        (多個參數以此類推)
       
        利用Session接口的find查詢
        find(String query)
        find(String query, Object[] values, Type[] types)
        find(String query, Object value, Type type)    均返回list  
        如:
        List list=session.find("select user from Users as user where user.name=?",name,Hibernate.STRING)
        List list=session.find("select user from Users as user where user.name=? and             user.pw=?",new Object[]{name,pw},new Type[]{Hibernate.STRING,Hibernate.STRING})
       
        {推薦使用Query的方法進行查詢}  
       
      第二部分:hibernate綜合查詢解決方案 (此部分詳細實例說明,如有不足的地方請寫信給我)        
     
       大家從第一部分可以看到,帶有參數的查詢,必須使用到Query接口,如上邊:
        Query query=session.createQuery("select users from Users as users where users.name=?");
        query.setString(0,name)//假設name爲傳過來的參數   
       但是在系統中如何才能寫一個公用的查尋方法呢?咋一看,似乎是不可以的,因爲每一次查詢的參數不一樣,參數的數量不一樣(如下代碼),那麼我們如何提取共性呢?   
         Query query=session.createQuery("select users from Users as users where users.name=? and users.pw=?");
        query.setString(0,name)//假設name爲傳過來的參數 
        query.setString(1,pw);
      
      首先說明,我的解決方案是從Seesion接口的find方法找到出口的,如下爲Session接口得find()方法之一:
        find(String query, Object[] values, Type[] types) 
      其中Object[]爲存放參數值的數組,Type[]爲存放參數類型的數組,他們的順序是和query裏“?” 的順序是相同的。那麼我爲什麼不用該find方法呢,因爲如果有分頁的情況,那麼該方法將不適用。
    
      下面詳細要說明的解決方案:
      首先我想創建三個新的對象:Paras.java(參數對象) ParasList.java(參數集合對象)HQuery.java
     (感謝我的同事camel提供註釋良好的代碼)
     1。Paras.java(參數對象)
    
  package com.ifreeway.homegrown.testing.waf;
  
  /**
   *
   * <p>Title:定義一個sql語句的條件參數類 </p>
   * <p>Description: 可以使用有序的參數集合傳送給sql/hql語句 </p>
   * <p>Copyright: Copyright (c) 2003</p>
   * <p>Company: ifreeway</p>
   * @author camel
   * @version 1.0
   */
  
  public class Paras {
   /**
    * 參數名稱
    */
   private Object pName;
   /**
    * 參數類型編碼,於java.sql.types中的類型保持一致
    */
   private int typeNo;
  
   public Object getPName() {
    return pName;
   }
   public void setPName(Object pName) {
    this.pName = pName;
   }
   public int getTypeNo() {
    return typeNo;
   }
   public void setTypeNo(int typeNo) {
    this.typeNo = typeNo;
   }
  } 
 
 2。ParasList.java(參數集合對象) 
  package com.ifreeway.homegrown.testing.waf;
  
  import java.util.ArrayList;
  
  /**
   *
   * <p>Title: 參數集合類</p>
   * <p>Description: 封裝sql/hql的參數到該集合類,便於處理和傳遞</p>
   * <p>Copyright: Copyright (c) 2003</p>
   * <p>Company: ifreeway</p>
   * @author camel
   * @version 1.0
   */
  
  public class ParaList extends ArrayList {
  
    /**
     * 在指定位置添加一個參數對象
     * @param index:參數的索引值
     * @param p:需要加入的參數對象
     */
    public  void addParas(int index,Paras p){
        super.add(index,p);
    }
  
    /**
     * 在集合的最後位置添加一個參數對象
     * @param p:需要加入的參數對象
     */
    public void addParas(Paras p){
      super.add(p);
    }
  
    /**
     * 取得指定位置的參數對象
     * @param index:參數的索引值
     * @return:參數對象
     */
    public Paras getParas(int index){
        return (Paras)super.get(index) ;
    }
    /**
     * 取得指定參數的索引
     * @param p:參數對象
     * @return:參數索引
     */
    public int indexofParas(Paras p){
       return super.indexOf(p) ;
    }
  
    /**
     * 從集合中去掉一個指定的參數對象
     * @param index:參數索引
     */
    public void removeParas(int index){
      super.remove(index) ;
    } 
  
  } 
 3。HQuery.java
  package com.ifreeway.homegrown.testing.waf;
  
  
  /**
   *
   * <p>Title: HQL的語句封裝類</p>
   * <p>Description: 該對象封裝HQL的查詢語句,參數集合,排序參數,分組參數,單頁起始地址  </p>
   * <p>Copyright: Copyright (c) 2003</p>
   * <p>Company:ifreeway </p>
   * @author camel
   * @version 1.0
   */
  
  public class HQuery {
  
    /**
     * HQL查詢語句
     */
    private String queryString;
    /**
     * 參數集合對象
     */
    private ParaList paralist;
    /**
     * 排序字段
     */
    private String orderby;
    /**
     * 分組字段
     */
    private String groupby;
    /**
     * 分頁起始查詢地址
     */
    private int pageStartNo;
  
    /**
     * 取得一個Hibernate的Query對象
     * @return:Query對象
     */
    public String getQueryString() {
      return queryString;
    }
  
    /**
     * 設置一個HQL查詢字符串
     * @param queryString:查詢字符串
     *
     */
    public void setQueryString(String queryString) {
  
     this.queryString =queryString;
  
    }
  
    /**
     * 取得參數集合對象
     * @return:參數集合對象
     */
    public ParaList getParalist() {
      return paralist;
    }
  
    /**
     * 設置參數集合對象
     * @param paralist:參數集合對象
     */
    public void setParalist(ParaList paralist) {
      this.paralist = paralist;
    }
  
    /**
     * 取得排序字段
     * @return:排序字段
     */
    public String getOrderby() {
      return orderby;
    }
  
    /**
     * 設置排序字段
     * @param orderby
     */
    public void setOrderby(String orderby) {
      this.orderby = orderby;
    }
  
    /**
     * 取得分組字段
     * @return
     */
    public String getGroupby() {
      return groupby;
    }
  
    /**
     * 設置分組字段
     * @param groupby
     */
    public void setGroupby(String groupby) {
      this.groupby = groupby;
    }
  
    /**
     * 取得頁起始地址
     * @return
     */
    public int getPageStartNo() {
      return pageStartNo;
    }
  
    /**
     * 設置頁起始地址
     * @param pageStartNo
     */
    public void setPageStartNo(int pageStartNo) {
      this.pageStartNo = pageStartNo;
    }
  } 
  
 上面三個對象的關係是:
 
 用Paras來裝載每一個查詢參數
  Paras paras=new Paras();
  paras.setPName(...);
  paras.setTypeNo(...);
 然後放在ParasList中
  ParasList paraslist=new ParasList();
  paraslist.add(paras)
 最後把填充以後的ParasList集合給HQuery 
  HQuery hquery=new HQuery();
  hquery.setParalist(paraslist);
  
 先面我們寫一個公用查尋方法,來實現我們的綜合查詢:
 
 /**
  *
  *  綜合查詢,首先實例化HQuery
  * @see com.ifreeway.homegrown.testing.common.waf.DBHandler#find(com.ifreeway.homegrown.testing.common.waf.HQuery)
  */
 public List find(HQuery _query) throws HibernateException {
  List itr = null;
  try {
   StringBuffer query_str = new StringBuffer(_query.getQueryString());
   //是否要排序
   if (_query.getOrderby() != null) {
    query_str.append(_query.getOrderby());
   }
   //是否要分組
   if (_query.getGroupby() != null) {
    query_str.append(_query.getGroupby());
   }
   Session session = getSession();
   Query query = session.createQuery(query_str.toString());
   if (_query.getParalist() != null) {
    List list = _query.getParalist();
    for (int i = 0; i < list.size(); i++) {
     Paras param = (Paras) list.get(i);
     switch (param.getTypeNo()) {//此處要根據參數類型的增加要增加相應的“case”
      case Types.VARCHAR :
       query.setString(i, param.getPName().toString());
       break;
      case Types.INTEGER :
       query.setInteger(
        i,
        ((Integer) param.getPName()).intValue());
       break;
      case Types.DATE :
       query.setDate(i, (java.sql.Date) param.getPName());
       break;
      case Types.DOUBLE :
       query.setDouble(
        i,
        ((Double) param.getPName()).doubleValue());
       break;
      case Types.BOOLEAN :
       query.setBoolean(
        i,
        ((Boolean) param.getPName()).booleanValue());
       break;
      case Types.CHAR :
       query.setCharacter(
        i,
        ((Character) param.getPName()).charValue());
       break;
      case Types.JAVA_OBJECT :
       query.setEntity(i, (BaseModel) param.getPName());
       break;
     }
    }
   }
   //是否存在分頁,當_query.getPageStartNo()==0是不分頁
   if (_query.getPageStartNo() != 0) {
    int pageno = _query.getPageStartNo();
    query.setFirstResult((pageno - 1) * Constants.RECORD_PER_PAGE);
    query.setMaxResults((pageno) * Constants.RECORD_PER_PAGE);
   }
   itr = query.list();
   closeSession();
  } catch (Exception e) {

  }
  return itr;
 } 
    
      好了一旦我們做好了上邊的工作,查詢對我們來說將是很容易的一件事情,而且可以達到公用,是不是省了許多力氣?下面我將實例化一個例子來進一步說明:
     
      例子:
      HQuery hquery=HQuery();
      hquery.setQueryString("select users from Users as users where users.name=? and users.sex=?");
      hquery.setOrderby("order by users.age desc");
     
      //如果要分頁,把當前頁curpage傳遞給hquery
      hquery.setPageStartNo(curpage);
     
      //實例化參數,本例爲兩個參數
      Paras paras1=new Paras();
      paras1.setPName(name);
      paras1.setTypeNo(Types.VARCHAR);
     
      Paras paras2=new Paras();
      paras2.setPName(sex);
      paras2.setTypeNo(Types.INTEGER);
     
      ParasList paraslist=new ParasList();
      paraslist.add(paras1);
      paraslist.add(paras2);//注意順序
     
      hquery.setParalist(paraslist);
     
      //好了,做好準備工作,調用查尋方法得到結果
      List list=find(hquery);
     
      完成,有興趣的網又可以據此跳到find中看看具體執行情況,如果這樣相信你會有更進一步得了解。還是那句話,這個解決方案也有不足的地方,如果你有更好的意見或方法,請和我聯繫。
     
      Jplateau

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章