傳智播客學習筆記5.20
HIBERNATE
湯陽光老師
HQL或Criteria
Query q = session.createQuery(hql);
類名上按ctrl+t,可以列出類的繼承結構
練習:
1, 根據使用者名和密碼查詢一個使用者.
2, 查詢有指定權限的組.
3, 如果把使用者按年齡升序排列, 找出排在指定使用者上面的那個使用者(假設年齡都不相同).
4, 樹形的Group中, 方法 findGroups(Group parent) 查詢指定Group的所有子組,
如果parent=null, 則傳回所有的頂級Group.
二級緩存
* 查詢
Hibernate提供的查詢方式有:HQL或Criteria。
** HQL
HQL是面向對象的查詢語言,他查的是對象而不是表。HQL中的對象名和屬性是區
分大小寫的(除了JAVA類和屬性其他部分不區分大小寫)。HQL主要通過Query來
操作,Query的建立方式:Query q = session.createQuery(hql);
*** 1, from
查詢所有User實體:
from User
要查詢的實體的名字應是全限定名,除非映射檔案中的hibernate-mapping的
auto-import屬性的值為true,才可以使用非全限定名(預設值為true)。如果系
統中存在多個重名(非全限定名相同)的情況下,應把auto-import都設為false。
*** 2, select
實作上面的功能也可以寫成:
select u from User as u
這裡使用as關鍵字指了一個别名u,其中as關鍵字可以省略。
也可以隻查詢幾個屬性,例如隻查詢所使用者名的id和name屬性:
select u.id,u.name from User u
這時傳回的每一結果都是一個Object數組,數組的第一個元素是id的值,第二個
元素是name的值。
讓上面的查詢傳回是一個個User對象,隻填充了id和name的屬性:
select new User(u.id,u.name) from User u
這樣要求User對象有一個隻接受id和name的構造方法:
public User(int id, String name)
在使用"select new Group(g.id,g.name) from Group g"語句進行查詢時報錯,
是因為Group為關鍵字. 應改為如下語句(使用全限定名):
select new cn.itcast.entities.Group(g.id,g.name) from Group g
*** 3, where
使用where子句進行過濾,例如查詢所有id值小于10的User:
from User u where u.id < 10
其中的u.id是指的實體的屬性(而非他映射的列名)。如果屬性名與關鍵字沖突
的話,就在前面加上實體的别名,例如u.order或u.desc等。
*** 4, order by
可以使用order by指定排序,如 from User u order by u.id desc .
*** 5.聚集函數
avg,count,max,min,sum
可以使用聚集函數:count(),max(),min()等。例如查詢所有使用者的總數:
select count(u) from User u
注意,這裡傳回的值可能是Integer類型,也可能是Long型,這是由jdbc驅動
決定的,是以使用時要注意。我們可以把傳回值轉為Number, 然後根據需要取
intValue或longValue.
大多數sql的表達式在where子句中都允許使用。Hibernate還提供有操作集合的函
數:size(),集合的大小; maxelement()和minelement(),引用一個基本資料類
型的集合中的最大與最小的元素;minindex()與maxindex(),引用有序集合的最
小與最大的索引;elements(),傳回集合的元素;等等,他們都需要一個集合類
型的參數。
查詢含有某個權限的組:
from Group g where ? in elements(g.privileges)
還需要設定一個參數,這個參數是Privilege的一個對象執行個體。
*** 使用參數
有兩種方式:
1,使用?占位,例:from User where id > ?,指定參數值使用
Query.setParameter(int position, Object val),位置索引從0開始;
2, 或使用變量名占位,例:from User where id > :id,指定參數值是使用
Query.setParameter(String name, Object val);
*** Query的分頁支援和查詢的方法
Query.list() 是傳回一個List集合;
Query.iterate() 傳回一個Iterator,這是先查詢出所有的id,再一條一條
的查詢記錄;
Query.uniqueResult() 是傳回唯一的結果或null(無比對時),如果有多條記錄
比對,則抛異常NonUniqueResultException。
分頁是通過Query.setFirstResult() 與Query.setMaxResults() 實作。
*** 練習
1, 根據使用者名和密碼查詢一個使用者.
2, 查詢有指定權限的組.
3, 如果把使用者按id升序排列, 找出排在指定使用者上面的那個使用者.
4, 樹形的Group中, 方法 findGroups(Group parent) 查詢指定Group的所有子組,
如果parent=null, 則傳回所有的頂級Group.
* Criteria 與 DetachedCriteria
Criteria是一種比HQL更面向對象的查詢方式。
*** Criteria的建立方式:
Criteria c = session.createCriteria(User.class);
*** 添加過濾條件:
c.add(Restrictions.gt("id",3)); // id的值要大于3
c.add(Restrictions.isNull("desc")); // desc不能為空
這樣添加的條件之間是 and 的關系。添加or關系的條件使用:
c.add(Restrictions.or(Restrictions.eq("name", "xx"),
Restrictions.eq("name", "yy")));
這是查詢名字為'xx'或'yy'的組。
*** 指定排序:
c.addOrder(Order.desc("id")); // 按id的值降序排列
*** 分頁:
Criteria.setFirstResult(0);
Criteria.setMaxResults(10);
*** 練習
1, 查找指定名字的使用者(測試使用者名是否已被使用).
2, 查找所有屬于 名字為'xx'的組的 使用者:
Criteria c = session.createCriteria(User.class);
c.createAlias("group", "g"); // 建立連接配接查詢
c.add(Restrictions.eq("g.name", "xx"));
(不能寫成c.add(Restrictions.eq("group.name", "itcast"));這樣會把
group.name當成是一個屬性)
** DetachedCriteria
DetachedCriteria可在session外建立(在其他層建立比如在Service中建立)然
後用getExecutableCriteria(session)方法建立Criteria對象來完成查詢。
*** 練習
DetachedCriteria 可以在 QueryArgs.buildCriteria方法中建構查詢.
* 緩存
緩存的作用主要用來提高性能,可以簡單的了解成一個Map;
class Xxx{
Map<Integer, Object> cache = new HashSet<Integer, Object>();
public User get(int id){
User user = cache.get(id);
if(user == null){
user = "select from database";
cache.put(user.getId(), user);
}
return user
}
}
一級緩存,Session級共享。每個Session會在内部維護一個資料緩存,此緩存随
着Session的建立/銷毀而建立/銷毀。save, update, saveOrUpdate, load,
get, list, iterate等這些方法都會将對象放在一級緩存中,一級緩存不能控制
緩存的數量,是以要注意大批量操作資料時可能造成記憶體溢出;可以用evict,
clear方法清除緩存中的内容。
二級緩存:配置:二級緩存是SessionFactory級别的全局緩存,它底下可以使用
不同的緩存類庫,hibernate内置了對EhCache, OSCache, TreeCache,
SwarmCache的支援,可以通過實作CacheProvider和Cache接口來加入Hibernate
不支援的緩存實作。使用時要在hibernate.cfg.xml中增加配置:
<property name="cache.provider_class">
org.hibernate.cache.HashtableCacheProvider
</property>
其中内置的緩存實作在文檔19.2. The Second Level Cache中有說明。
以上隻是說明可以使用二級緩存,具體的使用是每個類的緩存單獨存放,也需要
單獨配置。 使用方式為:在hibernate.cfg.xml中增加:
<class-cache class="className" usage="read-only"/>
或在映射檔案的class元素加入子元素:
<cache usage="read-write"/>
其中usage:read-only,read-write,nonstrict-read-write,transactional。如果
應用程式隻需讀取一個持久化類的執行個體,而無需對其修改,應可以對其進行隻讀
(read-only)緩存;如果應用程式需要更新資料,那麼使用讀/寫緩存(read-write)
比較合适。
論壇中 dao 的實作. (!! 取泛型參數)
論壇中事務的控制(不使用session就不應建立).
遇到能力範圍之内的代碼,湯老師往往讓我們自行編寫,然後再把代碼發給他進行點評。确實很有效地激發了學習的動力。我努力讓自己的代碼寫得更加優雅,雖然很難~~
當然,這樣對老師的要求很高,因為需要了解學生的思路,還要迅速分析出這麼寫的優缺點。當然,最大的挑戰是,老師往往需要看好幾份很爛的代碼,哈哈。