Hibernate query language。hql查詢中關鍵字不區分大小寫,但是類和屬性都是區分大小寫的。
1.簡單屬性查詢。
單一屬性查詢,返回屬性結果集列表,元素類型和實體類的相應的類型一致。
- for (Iterator iter=students.iterator(); iter.hasNext();) {
- String name = (String)iter.next();
- System.out.println(name);
- }
List students = session.createQuery("select name from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
String name = (String)iter.next();
System.out.println(name);
}
//返回結果集屬性列表,元素類型和實體類中的屬性類型一致
多個屬性查詢,多個屬性查詢返回數組對象,對象數組的長度取決於屬性的個數,對象數組中的元素類型與實體類中屬性一致。
- List students = session.createQuery("select id, name from Student").list();
- for (Iterator iter=students.iterator(); iter.hasNext();) {
- Object[] obj = (Object[])iter.next();
- System.out.println(obj[0] + ", " + obj[1]);
- }
List students = session.createQuery("select id, name from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
2.實體對象查詢
List students = session.createQuery("from Student").list();
當然這種hql語句,可以使用別名,as可以省去,如:from Student as s,若是使用select關鍵字,則必須使用別名。如:select s from Student as s.但是不支持select * from Student格式。
查詢中使用list和Iterate區別:
list查詢是直接運行查詢的結果,所以只有一句sql語句。而iterate方法則有可能會產生N+1條sql語句。這是怎麼回事呢?要理解N+1條語句,首先得弄明白iterate是如何執行查詢的?
首先發出一條查詢對象ID的語句,然後根據對象的ID到緩存(緩存的概念上篇博客已經提到)中查找,若是存在查詢出此對象的其他的屬性,否則會發出N條語句,此時的N語句,是剛纔第一次查詢的記錄條數。這種現象就是N+1sql語句。
其中list是默認情況下都發出sql語句,查詢出的結果會放到緩存中,但是它不會利用緩存,即使放進去,下次執行時,仍然繼續發出sql語句。
而:iterate默認情況下會利用緩存,若是緩存中有則不會發出N+1條語句。
3.條件查詢。
這種方式就是傳入參數,使用參數佔位符“?”。也可以使用“:參數名”
java代碼如下:
- List students = session.createQuery("select s.id, s.name from Student s where s.name like ?")
- .setParameter(0, "%0%")
- .list();
- List students = session.createQuery("select s.id, s.name from Student s where s.name like :myname")
- .setParameter("myname", "%0%")
- .list();
List students = session.createQuery("select s.id, s.name from Student s where s.name like ?")
.setParameter(0, "%0%")
.list();
List students = session.createQuery("select s.id, s.name from Student s where s.name like :myname")
.setParameter("myname", "%0%")
.list();
4.使用原生sql語句。
和咱們原先寫入的sql語句一樣。在此不介紹了。
5.外置命名查詢。
這個聽起來有點晦澀,怎麼理解呢?其實通俗的說就是把hql語句寫在外面,寫在映射文件中。使用標籤:
- <query name="queryStudent">
- <![CDATA[
- select s from Student s where s.id <?
- ]]>
- </query>
<query name="queryStudent">
<![CDATA[
select s from Student s where s.id <?
]]>
</query>
那在程序中是如何使用此標籤的呢?使用session.getNameQuery(),並進行賦值,代碼如下:
- .setParameter(0, 10)
- .list();
List students = session.getNamedQuery("queryStudent")
.setParameter(0, 10)
.list();
6.查詢過濾器。
這個是什麼意思呢?過濾器大家很熟悉吧,不熟悉的可以參考我的以前博客<>.原來我們接觸過編碼過濾器,編碼過濾器就是爲了避免當時每個頁面需要設置編碼格式而提出的。這個查詢過濾器其實也是這個意思。若是代碼都需要某一句sql語句的話,可以考慮使用它。這樣可以避免每次都寫查詢語句。
使用如下:首先在映射文件中配置標籤:
- <filter-def name="testFilter">
- <filter-param type="integer" name="myid"/>
- </filter-def>
<filter-def name="testFilter">
<filter-param type="integer" name="myid"/>
</filter-def>
然後程序中如下使用並進行賦值:
- .setParameter("myid", 10);
session.enableFilter("testFilter")
.setParameter("myid", 10);
7.分頁查詢。
分頁查詢,這個肯定不陌生,因爲在做drp項目時,做的最多的是分頁,當時使用oracle數據庫,分頁查詢涉及到三層嵌套。直接傳入的參數爲:每頁的大小(記錄數),頁號。
Hibernate中給我們已經封裝好了,只要設置開始的頁號以及每頁的大小即可,不用親自動手寫嵌套的sql語句。
代碼如下:
- .setFirstResult(1)
- .setMaxResults(2)
- .list();
List students = session.createQuery("from Student")
.setFirstResult(1)
.setMaxResults(2)
.list();
8.對象導航查詢。
這個什麼意思呢?這個只要是用於一個類的屬性是另一個類的引用。比如:student類中有一個classes屬性。其中的classes也是一個類Class的引用。
當我們查詢的時候可以這樣使用:
- List students = session.createQuery("from Student s where s.classes.name like '%t%'")
- .list();
List students = session.createQuery("from Student s where s.classes.name like '%t%'")
.list();
相當於:s.getClasses.getName(),直接使用get後面的屬性,然後首字母小寫。
這種語法,是不是很熟悉?想想我們在哪是不是也用過?想起來了嗎?估計你猜出來啦,呵呵,是JSTL(jsp standard tag library)中。若是想進一步瞭解,可以參考我的博客哈,當時是轉載滴貌似。
9.連接查詢。
連接分爲:內連接和外連接,其中外連接分爲左連接,右連接,完全連接。這個跟數據庫中的左右連接其實是一樣的。我們通俗解釋一下:
左連接:以左邊爲準,右邊即使沒喲匹配的,也要把這條記錄查詢出來,此時沒有匹配的右邊以null填充。
右連接:以右邊爲準,左邊即使沒有匹配的,也要把這條記錄查詢出來,此時沒有匹配的左邊以null填充。
完全連接:只要一方存在即可。
內連接:必須兩方都存在纔可以查詢提取此記錄。
10.統計查詢。
其實就是查詢count的記錄數。其中查詢出來的額count是long類型。
11.DML風格的操作。
DML?其實DML=Data Manipulate Language(數據操作語言),舉個例子:
- session.createQuery("update Student s set s.name=? where s.id<?")
- .setParameter(0, "王斌")
- .setParameter(1, 2)
- .executeUpdate();
session.createQuery("update Student s set s.name=? where s.id<?")
.setParameter(0, "王斌")
.setParameter(1, 2)
.executeUpdate();
假若原來的名字是:李四,更新完數據庫後變成王斌,若是我們此時取出數據,其姓名是李四還是王斌?按照道理應該是王斌,但是結果確實李四,若不信,可以自己去實踐一下。
這個原因,是因爲更新了數據庫,但是緩存中沒有更新,纔會造成這種數據庫和緩存不同步的問題。
所以,我們應該儘量不使用這種形式。揚其長避其短嘛。