Hibernate綜合查詢解決方案 (轉)

amyz發表於2007-11-26
Hibernate綜合查詢解決方案 (轉)[@more@]

查詢解決方案

  這兩個星期以來,我把原來用開發的一個測試工具改用struts+hibernate來實現,首先從心情上來,整個開發過程中始終保持愉快和平和,“原來開發可以這樣愉快?”,再一點就是開發上高效了許多。
  現在sun又加入jdocentral.com開始著手JDO2.0,想想看等它出臺以後將是一個怎樣激動人心得場面,讓我們拭目以待。
 
  用Hibernate來操縱持久資料非常簡單,在這裡一些簡單的查詢我會一筆帶過,本文著重說明在綜合查詢兼有分頁的時候我的一些,如果網友覺得我的方案還有不足的地方,也請和我討論,我的e:plateau_t@sina.com.
 
  第一部分:Hibernate提供的查詢介面或其方法(此部分不做深究,請參考hibernate手冊)
 
  1。根據ID查詢
   要用到Session介面的load方法。
   load(Class theClass, Serializable id)
   load(Class theClass, Serializable id, LockMode lockMode)
   load( object, Serializable id) 
   
  2。HQL語句進行查詢
 
  2。1 利用Query介面,Query由Session裡的createQuery()來產生一個查詢
    1)不帶引數的查詢(這類比較簡單)
    Query query=session.createQuery(" 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.(引數物件) ParasList.java(引數集合物件)HQuery.java
    (感謝我的同事camel提供註釋良好的程式碼)
   1。Paras.java(引數物件)
   
 package com.ifreeway.homegrown.testing.waf;
 
 /**
  *
  *

Title:定義一個語句的條件引數類


  *

Description: 可以使用有序的引數集合傳送給sql/hql語句


  *

Copyright: Copyright (c)


  *

Company: ifreeway


  * @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;
 
 /**
  *
  *

Title: 引數集合類


  *

Description: 封裝sql/hql的引數到該集合類,便於處理和傳遞


  *

Copyright: Copyright (c) 2003


  *

Company: ifreeway


  * @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;
 
 
 /**
  *
  *

Title: HQL的語句封裝類


  *

Description: 該物件封裝HQL的查詢語句,引數集合,排序引數,分組引數,單頁起始地址 


  *

Copyright: Copyright (c) 2003


  *

Company:ifreeway


  * @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.Handler#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


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-984960/,如需轉載,請註明出處,否則將追究法律責任。

相關文章