天天看點

傳智播客學習筆記5.20

傳智播客學習筆記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就不應建立).

遇到能力範圍之内的代碼,湯老師往往讓我們自行編寫,然後再把代碼發給他進行點評。确實很有效地激發了學習的動力。我努力讓自己的代碼寫得更加優雅,雖然很難~~

當然,這樣對老師的要求很高,因為需要了解學生的思路,還要迅速分析出這麼寫的優缺點。當然,最大的挑戰是,老師往往需要看好幾份很爛的代碼,哈哈。

繼續閱讀