hql(hibernate query language)功能強大。
首先回憶下之前我們接觸的對數據對象的操作:
①刪除session.delete(對象)
②保存session.save(對象) session.persist(對象)
③修改obj.setXXX();
④查詢session.load(***.class, 1) ; session.get(***.class, 1);
可是這樣只能進行簡單的數據操作,想要做較為復雜的操作,就要用到hql語句了。
hql的詳解
hibernate 設計者 推薦我們在設計表的時候,應當每張表有一個主鍵,而且該主鍵最好不含業務邏輯(不要有實際意義)
如:product 表
id productNo name price
1 bi001 冰箱 1000
2 nj111 電腦 2000
最好不要將產品編號設計成主鍵,產品編號假如變化那麼整個數據表就會變化,傷筋動骨,但是如果設計另外一個主鍵id不含業務信息
變編號名字價格數據都是穩定的。
我們使用hibernate工具,自動生成 domain 對象和映射文件,如果我們的表有主外鍵的關系,則應當先映射主表,再映射從表。
我們建立三張表:學生、學生所選課程、課程。
表的關系和映射文件的關系如下(到後面我們專門學到一對多、多對一、多對多等對應關系):
*檢索一個表中的所有數據對象:
List<Student> list= session.createQuery("from Student ").list;
* uniqueResult方法
如果我們檢索一個對象,明確知道最多只有一個對象,則建議使用該方法,效率更高:
具體用法如下:
Student s=(Student) session.createQuery("from Student where sid='20050003'").uniqueResult();
System.out.println(s.getSname());
*distinct的用法
過濾重復的記錄
//比如,顯示所有學生的性別和年齡.
List list=session.createQuery("select distinct sage,ssex from Student").list();
for(int i=0;i<list.size();i++){
Object [] objs=(Object[]) list.get(i);
System.out.println(objs[0].toString()+" "+objs[1].toString());
}
*between and..
List list=session.createQuery("select distinct sage,ssex,sname from Student where sage between 20 and 22").list();
for(int i=0;i<list.size();i++){
Object [] objs=(Object[]) list.get(i);
System.out.println(objs[0].toString()+" "+objs[1].toString()+objs[2].toString());
}
*in /not in
//查詢計算機系和外語系的學生信息
List<Student> list=session.createQuery("from Student where sdept in ('計算機系','外語系')").list();
//取出for 增強
for(Student s:list){
System.out.println(s.getSname()+" "+s.getSaddress()+" "+s.getSdept());
}
*group by使用
//顯示各個系的學生的平均年齡
List<Object[]> list=session.createQuery("select avg(sage),sdept from Student group by sdept").list();
//取出for 增強
for(Object[] obj:list){
System.out.println(obj[0].toString()+" "+obj[1].toString());
}
*having
1.對分組查詢後的結果,進行篩選:比如請顯示人數大於3的系名稱
List<Object[]> list=session.createQuery("select count(*) as c1,sdept from Student group by sdept having count(*)>3").list();
//取出for 增強
for(Object[] obj:list){
System.out.println(obj[0].toString()+" "+obj[1].toString());
}
//查詢各個系的女生有多個個
List<Object[]> list=session.
createQuery("select count(*) as c1,sdept from Student where ssex='F' group by sdept").list();
//取出for 增強
for(Object[] obj:list){
System.out.println(obj[0].toString()+" "+obj[1].toString());
}
2.查詢計算機系共多少人?->如果我們返回的是一列數據
//這時我們的取法是直接取出list->object 而不是 list->Object[]
List<Object[]> list=session.
createQuery("select sage from Student where sdept='計算機系'").list();
//取出for 增強
for(Object obj:list){
System.out.println(obj.toString());
}
3.查詢選修11號課程的最高分和最低分.
List<Object[]> list=session.
createQuery("select 11,max(grade),min(grade) from Studcourse where course.cid=11").list();
//取出for 增強
for(Object[] obj:list){
System.out.println(obj[0].toString()+" max="+obj[1].toString()+" min="+obj[2].toString());
}
4.計算各個科目不及格的學生數量.
List<Object[]> list=session.
createQuery("select count(*),student.sdept from Studcourse where grade<60 group by student.sdept").list();
//取出1. for 增強
for(Object[] obj:list){
System.out.println(obj[0].toString()+" "+obj[1].toString());
}
參數綁定案例 (jdbc->PreparedStatement setXXX)
使用參數綁定的好處有3:
面試題: 如果不使用參數綁定,怎樣防止登錄時, sql注入?
name password
思路: 通過用戶名,查詢出該用戶名在數據庫中對應的密碼,然後再與用戶輸入的秘密比較,如果相等,則用戶和法,否則,非法.
參數綁定有兩種形式
Query q=session.createQuery(from Student where sdept=:dept and sage>:age)
如果我們的參數是 :冒號形式給出的,則我們的參數綁定應當這樣:
List<Student> list=session.createQuery("from Student where sdept=:a1 and sage>:sage")
.setString("a1", "計算機系").setString("sage", "2").list();
還有一種形式:
Query q=session.createQuery(from Student where sdept=? and sage>?)
如果我們的參數是以 ? 形式給出的則,參數綁定應當:
List<Student> list=session.createQuery("from Student where sdept=? and sage>?")
.setString(0, "計算機系").setString(1, "2").list();
參數的綁定,可以分開寫:形式如下:
Query query=session.createQuery("from Student where sdept=? and sage>?");
query.setString(0, "計算機系");
query.setString(1, "2");
List <Student> list=query.list();
for(int i=0;i<list.size();i++){
Student s= list.get(i);
System.out.println(s.getSname()+" "+s.getSage());
}