??? 這兩個星期以來,我把原來用struts開發的一個測試工具改用struts+hibernate來實現,首先從心情上來,整個開發過程中始終保持愉快和平和,“原來開發可以這樣愉快?”,再一點就是開發效率上高效了許多。
??????現在sun又加入jdocentral.com開始著手JDO2.0,想想看等它出臺以后將是一個怎樣激動人心得場面,讓我們拭目以待。
??????
??????用Hibernate來操縱持久數據非常簡單,在這里一些簡單的查詢我會一筆帶過,本文著重說明在綜合查詢兼有分頁的時候我的一些經驗,如果網友覺得我的方案還有不足的地方,也請和我討論,我的email:plateau_t@sina.com.
??????
??????第一部分: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);