HQL是個中立的語言,即它跟任何數據庫都沒關系,你如果使用HQL的話通過數據庫方言都會翻譯成相應的數據庫的SQL語句,包括[排序,子查詢,調用SQL中的函數].
HQL中關鍵字是不區分大小寫的,但是屬性和類型是區分大小寫的。
1>.簡單屬性查詢
1>).單一屬性查詢,返回結果集屬性列表,元素類型和實體類中相應的屬性類型一致。如:
session = HibernateUtils.getSession();
session.beginTransaction();
//返回結果集屬性列表,元素類型和實體類中相應的屬性類型一致
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);
}
session.getTransaction().commit();
2>).多個屬性查詢,返回的集合元素是對象數組,數組元素的類型和對
應的屬性在實體類中的類型一致,數組的長度取決于select中屬性的個數。如:
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]);
}
3>).如果認為返回數組不夠對象化,可以采用HQL動態實例化Student對象,
但是Strudent類中必須提供相應的構造函數。如:
List students = session.createQuery("select new Student(id, name) from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getId() + "," + student.getName());
}
2>.實體對象查詢
1>).返回Student對象的集合,可以忽略select,表可以使用別名,別名可以用as也可以不用。如:
List students = session.createQuery("from Student s").list();
//List students = session.createQuery("from Student as s").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
2>).返回Student對象的集合,使用select查詢實體對象,必須采用別名。如:
List students = session.createQuery("select s from Student as s").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
3>).不支持select * from .....這樣的查詢語句。如:下面的語句是錯誤的
List students = session.createQuery("select * from Student").list();
4>).list和iterator的區別?
我們知道,session.createQuery()得到個Query,而從Hibernate API中我們可
以發現Query有兩個方法list()和iterator()用于返回結果集。它們的區別在
于:
*list每次都會發出sql語句,list會向緩存中放入數據,而不利用緩存中的數據
*iterator在默認情況下利用緩存數據,但如果緩存中不存在數據有可能出現N+1問題
5>).N+1問題
在默認情況下,使用query.iterator()查詢,有可能出現N+1問題
1: 首先發出一條查詢對象id列表的sql語句
N: 根據id列表到緩存中查詢,如果緩存中不存在與之匹配的數據,那么會根據
id發出相應的sql語句
如:
Iterator iter = session.createQuery("from Student").iterate();
while(iter.hasNext()) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
3>.條件查詢
1>).可以采用拼字符串的方式傳遞參數。如:
List students = session.createQuery("select s.id, s.name from Student s where s.name like '%1%'").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + "," + obj[1]);
}
2>).可以使用?方式傳遞參數,參數的索引從0開始;傳遞的參數值如果是字符型的,不用
單引號引起來;可以使用方法鏈編程。如:
List students = session.createQuery("select s.id, s.name from Student s where s.name like ?")
.setParameter(0, "%1%")
.list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + "," + obj[1]);
}
3>).可以使用 :參數名稱 的方式傳遞參數值。如:
List students = session.createQuery("select s.id, s.name from Student s where s.name like :myname")
.setParameter("myname", "%1%")
.list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + "," + obj[1]);
}
4>).如果傳遞多個參數,可以使用setParameterList方法。如:
List students = session.createQuery("select s.id, s.name from Student s where s.id in(:myids)")
.setParameterList("myids", new Object[]{1, 2, 3, 4, 5})
.list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + "," + obj[1]);
}
5>).在HQL中可以使用數據庫的函數,像mysql中的date_format。如:
List students = session.createQuery("select s.id, s.name from Student s where date_format(s.createTime, '%Y-%m')=?")
.setParameter(0, "2008-02")
.list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + "," + obj[1]);
}
6>).查詢某個日期段的數據。如:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//查詢2008-01-10到2008-02-15創建的學生
List students = session.createQuery("select s.id, s.name from Student s where s.createTime between ? and ?")
.setParameter(0, sdf.parse("2008-01-10 00:00:00"))
.setParameter(1, sdf.parse("2008-02-15 23:59:59"))
.list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + "," + obj[1]);
}
4>.Hibernate也支持直接使用sql查詢。如:
List students = session.createSQLQuery("select * from t_student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + "," + obj[1]);
}
5>.外置命名查詢,主要完成hql語句和程序的解耦合.
1>).在映射文件中采用<query>標簽來定義HQL語句。如:
<query name="searchStudents">
<![CDATA[
SELECT s FROM Student s where s.id<?
]]>
</query>
2>).在程序中采用session.getNamedQuery()方法得到HQL查詢串。如:
List students = session.getNamedQuery("searchStudents")
.setParameter(0, 10)
.list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
6>.查詢過濾器
1>).在影射文件中定義過濾器參數。如:
<filter-def name="filtertest">
<filter-param name="myid" type="integer"/>
</filter-def>
2>).在類的影射中使用這些參數。如:
<filter name="filtertest" condition="id < :myid"/><!--<轉義字符"<"-->
3>).在程序中啟用過濾器。如:
session.enableFilter("filtertest")
.setParameter("myid", 10);
List students = session.createQuery("from Student").list();//會在該session中所有的查詢后自動加上過濾器中的條件
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
參見:Student.hbm.xml,FilterQueryTest.java
7>.分頁查詢
1>).setFirstResult()從0開始
2>).setMaxResults每頁顯示多少條數據。如:
List students = session.createQuery("from Student")
.setFirstResult(1)
.setMaxResults(2)
.list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
8>.對象導航查詢
Hibernate支持對象的,因此可以用對象導航查詢。如:
Student類總有Classes類型的屬性classes,而Classes類有name屬性。我們通過classes的name來查詢student:
List students = session.createQuery("select s.name from Student s where s.classes.name like '%1%'").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
String name = (String)iter.next();
System.out.println(name);
}
9>.連接查詢
1>).內連接:只是把兩邊都有的記錄查出來,可以省略inner,并且只要影射文件中已經設好了表之間的關系,無須用on表示查詢條件。如:
//List students = session.createQuery("select c.name, s.name from Student s join s.classes c").list();
List students = session.createQuery("select c.name, s.name from Student s inner join s.classes c").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("select c.name, s.name from Classes c left join c.students s").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + "," + obj[1]);
}
3>).外右連接:把右邊表的所有記錄都顯示出來。如:
List students = session.createQuery("select c.name, s.name from Classes c right join c.students s").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + "," + obj[1]);
}
10>.統計查詢
1>).count。如:
Long count = (Long)session.createQuery("select count(*) from Student").uniqueResult();//返回的是單條記錄
System.out.println(count);
2>).group by。如:
List students =session.createQuery("select c.name, count(s) from Student s join s.classes c " +
"group by c.name order by c.name").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
11>.DML風格的操作(盡量少用,因為緩存不同步)
update和delete只會更新數據庫中的數據,而緩存中不會改,此時如果取得該數據還是緩存中的,而不會是更新后的,因此緩
存中的數據就成了臟數據了。如果批量更新的話,還會給內存帶來很大壓力。如:
session.createQuery("update Student s set s.name=? where s.id < ?")
.setParameter(0, "李四")
.setParameter(1, 5)
.executeUpdate();
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yangfeitarena/archive/2009/04/17/4086334.aspx