標籤:style class blog code java http
上篇文章討論了hql查詢中的串連查詢,它的查詢文法在功能上和sql的串連查詢是相同的,內串連查詢取得的是關係之間的笛卡爾積,外串連查詢是擷取一個關係表及與另一個關係表的合集部分,具體的使用方法見上篇文章,並在最後討論了外置命名查詢的方法。該篇文章將會對hql的參數查詢、函數查詢及查詢過濾器做詳細的討論。
一、參數查詢
參數查詢其實是使用等價代換的方法,使用設定的值替換字串中指定位置的符號,或者通過使用參數名稱,使用字串來替換參數名稱的值,這樣能避免sql注入的問題,拼接字串會出現sql注入的問題。hql提供了兩種參數查詢的方法,一種是通過使用符號“?”,然後使用setParameter方法設定替換的字串;另外一種是使用參數名稱,定義參數名稱,並使用setParameter方法來替換指定參數名稱的字串。
1.1 參數符號--?
通過使用符號?來設定要添加的參數內容,也就是說這裡的符號?其實是hql的參數。如果想要為參數賦值,可以使用hql的方法setParameter,該方法重載參數,提供兩個參數,一個能夠傳遞參數出現的位置,另一個為參數賦值。具體如下代碼:
@SuppressWarnings({ "unchecked", "rawtypes" })public void testQuery(){Session session=null;try{session=HibernateUtils.getSession();session.beginTransaction();//方法鏈編程List students=session.createQuery("select s from Student s where s.name like ?").setParameter(0, "%0%").list();for(Iterator iter=students.iterator();iter.hasNext();){Student student=(Student)iter.next();System.out.println(student.getName());}session.getTransaction().commit();}catch(Exception e){e.printStackTrace();session.getTransaction().rollback();}finally{HibernateUtils.closeSession(session);}}
在需要使用參數的字串位置處使用?來代替,然後使用setParameter 方法,替換參數的內容。該方法中的第一個參數可以是字串也可以是索引,如果使用了?作為參數,就必須指定?的第幾個索引。
1.2 參數名稱
上文已經討論了符號參數的使用方法,並稍微簡介了參數名稱查詢的方法,也就是說可通過使用參數名稱的方法來定義參數,這種方法需要指定參數的名稱,然後使用setParameter來設定名稱替換參數,hql的參數定義是冒號+參數名。
@SuppressWarnings({ "unchecked", "rawtypes" })public void testQuery(){Session session=null;try{session=HibernateUtils.getSession();session.beginTransaction();//可以採用 :參數名 的方式傳遞參數//方法鏈編程List students=session.createQuery("select s from Student s where s.name like :myname").setParameter("myname", "%0%").list();for(Iterator iter=students.iterator();iter.hasNext();){Student student=(Student)iter.next();System.out.println(student.getName());}session.getTransaction().commit();}catch(Exception e){e.printStackTrace();session.getTransaction().rollback();}finally{HibernateUtils.closeSession(session);}}
在上面的樣本中使用了like模糊查詢,查詢在學生的姓名中有0出現的所有的學生資訊,查詢字串中定義了一個名稱為myname的參數,並使用setParameter為參數賦值。
1.3 參數集合
上文簡單介紹了hql單個參數的使用方法,非常簡單,那如果字串中需要配置多個串連的參數怎麼辦呢,那要使用setParameter一個個的進行賦值嗎?hql提供了setParameterList來為參數舒服賦值,如下樣本:
@SuppressWarnings({ "unchecked", "rawtypes" })public void testQuery5(){Session session=null;try{session=HibernateUtils.getSession();session.beginTransaction();//可以採用 :參數名 的方式傳遞參數//方法鏈編程List students=session.createQuery("select s from Student s where s.id in(:ids)").setParameterList("ids",new Object[]{1,2,3,4}).list();for(Iterator iter=students.iterator();iter.hasNext();){Student student=(Student)iter.next();System.out.println(student.getName());}session.getTransaction().commit();}catch(Exception e){e.printStackTrace();session.getTransaction().rollback();}finally{HibernateUtils.closeSession(session);}}
上例中使用了集合查詢in,在集合中查詢符合集合要求的內容,定義了名為ids的參數,參數的具體內容是一個對象集合,使用setParameterList為參數做了賦值。
二、函數查詢
hql的具體查詢提供了基本的sql查詢方法,同樣也支援對應資料庫的函數查詢方法,可以在查詢語句中使用資料庫函數來設定查詢內容的格式及想要查詢的內容,如日期格式函數date_format:
@SuppressWarnings({ "unchecked", "rawtypes" })public void testQuery(){Session session=null;try{session=HibernateUtils.getSession();session.beginTransaction();//日期函數List students=session.createQuery("select s from Student s where date_format(s.createTime,'%Y-%m')=?").setParameter(0,"2009-07").list();for(Iterator iter=students.iterator();iter.hasNext();){Student student=(Student)iter.next();System.out.println(student.getName());}session.getTransaction().commit();}catch(Exception e){e.printStackTrace();session.getTransaction().rollback();}finally{HibernateUtils.closeSession(session);}}
上例中是按照學生資訊的建立時間來查詢相應的學生資訊,通過使用date_format()方法來將字串轉化為相應查詢內容的格式來擷取的查詢內容。
另外也可以使用資料庫的between...and...來查詢某一範圍內的資料,如下樣本查詢某一時間段內的學生資訊:
@SuppressWarnings({ "unchecked", "rawtypes" })public void testQuery(){Session session=null;try{session=HibernateUtils.getSession();session.beginTransaction();//查詢時間段List students=session.createQuery("select s from Student s where date_format(s.createTime,'%Y-%m') between ? and ?").setParameter(0,"2009-07").setParameter(1,"2012-07").list();for(Iterator iter=students.iterator();iter.hasNext();){Student student=(Student)iter.next();System.out.println(student.getName());}session.getTransaction().commit();}catch(Exception e){e.printStackTrace();session.getTransaction().rollback();}finally{HibernateUtils.closeSession(session);}}
彙總查詢,hql不支援*查詢,但是可以使用count(*)查詢。想要使用group by分組語句就必須在語句使用使用彙總函式。如下樣本示範的是hql彙總函式和分組查詢的使用方法:
@SuppressWarnings({ "unchecked", "rawtypes" })public void testQuery(){Session session=null;try{session=HibernateUtils.getSession();session.beginTransaction();//返回結果集屬性列表,元素類型和實體類中的屬性類型一致List students=session.createQuery("select c.name,count(s) from Classes c join c.students s group by c.name order by c.name").list();for(Iterator ite=students.iterator();ite.hasNext();){Object[] obj=(Object[])ite.next();System.out.println(obj[0]);}session.getTransaction().commit();}catch(Exception e){e.printStackTrace();session.getTransaction().rollback();}finally{HibernateUtils.closeSession(session);}}
擷取第一行,hql提供了方法來擷取結果集中的第一行資料,該方法為uniqueResult(),通過使用sql語句來擷取的結果集,然後在方法鏈中使用uniqueResult()方法來擷取預設第一行的資料,如下代碼:
<pre name="code" class="java">@SuppressWarnings({ "unchecked", "rawtypes" })public void testQuery(){Session session=null;try{session=HibernateUtils.getSession();session.beginTransaction();//返回結果集屬性列表,元素類型和實體類中的屬性類型一致//List students=session.createQuery("select count(*) from Student").list();//Long count=(Long)students.get(0);//上面的查詢方法,類似於下面使用的uniqueResult()方法Long count=(Long)session.createQuery("select count(*) from Student").uniqueResult();System.out.println("count="+count);session.getTransaction().commit();}catch(Exception e){e.printStackTrace();session.getTransaction().rollback();}finally{HibernateUtils.closeSession(session);}}
上面的程式碼範例提供了兩種方法來擷取第一行的資料,一種是通過使用get()方法,擷取結果集中的第幾行的內容;另外一種使用的是uniqueResult()方法來擷取新行的內容。
三、查詢過濾器
查詢過濾器提供了對查詢的內容進行過濾的過程,在對應檔中定義過濾器,程式中啟用過濾器,並為過濾器參數賦值。具體步驟為:首先在要查詢的實體物件的映射中使用<filter-def>標籤配置過濾器,並在相對應的<class>標籤中添加對應的<filter>過濾器;然後在對應的程式檔案中使用enableFilter()方法啟動過濾器,為過濾器定義的參數賦值,在執行時就會自動自行對應的過濾器。
清單一:對應檔,在對應檔中配置對應的過濾器,對應檔中定義了名為testFilter的過濾器,在class中為過濾器添加了執行條件,並在條件中添加了執行參數myid。
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.src.hibernate.Student" table="t_student"><id name="id"><generator class="native"/></id><property name="name"/><property name="createTime"></property><!-- 在多的一端Student中添加一行新的Classes列 ,並且列的名稱要和Classes.hbm.xml的列明相同--><many-to-one name="classes" column="classesid"></many-to-one><!-- 使用過濾器,指定id的內容要小於參數:myid配置的內容--><filter name="testFilter" condition="id < :myid"></filter></class><!-- 定義查詢過V領器 --><filter-def name="testFilter"><filter-param type="integer" name="myid"></filter-param></filter-def></hibernate-mapping>
清單二:程式檔案,在程式檔案中使用enableFilter啟用過濾器,並為過濾器的參數賦值。
@SuppressWarnings({ "unchecked", "rawtypes" })public void testQuery(){Session session=null;try{session=HibernateUtils.getSession();session.beginTransaction();session.enableFilter("testFilter").setParameter("myid",10);//返回結果集屬性列表,元素類型和實體類中的屬性類型一致List students=session.createQuery("from Student").list();for(Iterator ite=students.iterator();ite.hasNext();){Student obj=(Student)ite.next();System.out.println(obj.getName());}session.getTransaction().commit();}catch(Exception e){e.printStackTrace();session.getTransaction().rollback();}finally{HibernateUtils.closeSession(session);}}
結語
hql的基本查詢方法已經討論完成,主要針對hql的使用過程中需要注意的內容作了詳細的討論,在每一種查詢方法中都添加了相應的樣本,通過樣本加深對hql查詢方法的使用,有sql基礎的在使用hql時會非常的簡單。