Hibernate框架學習(第四講)---持久化對象狀態

之前文章中我們提到過持久化定義時,提及到瞬時狀態和持久化狀態。而一個持久化示例可能存在的狀態有三種:

瞬時狀態:

該實例是剛用new語句創建的,還沒有被持久化,不處於任何Session的緩存中。它沒有持久化標識(相當於主鍵值)。處於瞬時狀態的實例被稱爲瞬時對象。它的特點是:
不和任何一個Session實例關聯。在數據庫中沒有對應的記錄。

持久化(persistent)狀態:

已經被持久化,加入到Session緩存中。處於持久化狀態的實例被稱爲持久化對象。
實例目前與某個Session有關聯。 它擁有持久化標識(相當於主鍵值),並且可能在數據庫中有一個對應的行。 Hibernate保證在同一個Sesion實例的緩存中,數據庫中的每條記錄只對應唯一的持久化對象。 它的特點是:
持久化對象總是被一個Session實例關聯。持久化對象和數據庫中的相關記錄對應。Session在清理緩存時,會根據持久化對象的屬性變化,來同步更新數據庫。

脫管(detached)狀態:

已經被持久化過,但不再處於Session的緩存中。處於脫管狀態的實例被稱爲脫管對象。實例曾經與某個持久化上下文發生過關聯,不過那個上下文被關閉了, 或者這個實例是被序列化(serialize)到另外的進程。 它擁有持久化標識,並且在數據庫中可能存在一個對應的行。 對於脫管狀態的實例,Hibernate不保證任何持久化標識和Java標識的關係。它的特點是:
不再位於session的緩存中,即它不再和session關聯。它擁有持久化標識。

Session的saveOrUpdate()方法:

Session的save()方法:使用一個臨時對象轉變爲持久對象。
方法簽名:public Serializable save(Object object) throws HibernateException; 它完成以下操作:
1) 把持久化類的實例加入到緩存中,使它變爲持久化對象。
2) 選用映射文件指定的標識符生成器爲持久化對象分配唯一的OID。
3) 計劃執行一個insert語句,把持久化對象當前的屬性值組裝到insert 語句(SQL DML)中。值得注意的是,save()方法並不是立即執行SQL insert語句。只有當Session清理緩存時,纔會執行SQL insert語句。
另外,需要注意的是:Hibernate通過持久化對象的OID來維持它和數據庫相關記錄的對應關係。所以當持久化的實例處於持久化狀態時,不允許程序隨意修改它的OID。其實,無論java對象處於瞬時狀態、持久化狀態還是脫管狀態,程序都不應該修改它的OID。

Session的update()方法:使一個脫管對象轉變爲持久化對象。
方法簽名:public void update(Object object) throws HibernateException; 它完成以下操作:
1) 把脫管對象重新加入到Session緩存中,使它變爲持久化對象。
2) 計劃執行一個update語句。值得注意的是,Session只有在清理緩存的時候纔會執行update語句,並且在執行時纔會把持久化對象當前的屬性值組裝到update語句中。

Session的saveOrUpdate()方法:
方法簽名:public void saveOrUpdate(Object object) throws HibernateException ; saveOrUpdate()方法同時包含了save()與update()方法的功能,如果傳入的參數是瞬時對象,就調用save()方法;如果傳入的參數是脫管對象,就調用update()方法;如果傳入的參數是持久化對象,方法就直接返回。那麼,saveOrUpdate()方法如果判斷一個對象處於瞬時狀態不是脫管狀態呢?如果滿足以下情況之一,Hibernate就把它作爲臨時對象:
1) Java對象的OID取值爲null。
2) Java對象具有version屬性,並且取值了null。
3) 在映射文件中爲元素設置了unsaved-value屬性,並且OID取值與unsaved-value屬性值匹配。
4) 在映射文件中爲元素設置了unsaved-value屬性,並且version屬性取值與unsaved-value屬性值匹配。
5) 自定義了Hibernate的Interceptor實現類,並且Interceptor的isUnsaved()方法返回Boolean.TRUE。

Session的delete()方法:
方法簽名:public void delete(Object object) throws HibernateException; delete()方法用於從數據庫中刪除與Java對象對應的記錄。如果傳入的參數是持久化對象,Session就計劃執行一個delete語句。如果傳入的參數是遊離對象,先使遊離對象被Session關聯,使它變爲持久化對象,然後計劃執行一個delete語句。值得注意的也是,Session只有在清理緩存的時候纔會執行delete語句。

Query接口

使用 “?”按參數位置綁定:
通過Query接口執行HQL語句時,可以先設定查詢參數,然後通過setXXX()方法來綁定參數。如下

Query query = session.createQuery("from User as u where u.age > ? and u.name like ?");
query.setInteger(0, 25);
query.setString(1, "%a%");
List list = query.list();

Hibernate提供了綁定各種類型的參數的方法,如參數爲字符串類型,可調用setString(),如果參數爲整數類型,可調用setInteger()方法,以此類推。這些setXXX()方法的第1個參數HQL查詢語句中參數的位置,第2個參數代表HQL查詢語句中參數的值。
使用 “:” 後跟變量名來按命名參數綁定:
可以使用命名參數來取代使用“?”設置參數的方法,這可以不用依照特定的順序來設定參數值,如上例可改成:
Query query = session.createQuery(“from User as u where u.age > :minAge and u.name like likeName”);
query.setInteger(“minAge”, 25);
query.setString(“likeName”, “%a%”);
List list = query.list();
使用命名參數方式的綁定方式有以下優勢:
1) 代碼可讀性更好。
2) 命名參數不依賴它們在查詢字符串中出現的位置。
3) 在同一個查詢中可以多次使用。
所以,應該優先考慮使用命名參數方式。

使用命名查詢(nameQuery):
可以將HQL語句編寫在程序之外,以避免硬編碼在程序之中,這樣要修改HQL語句時就很方便。在xxx.hbm.xml中使用標籤,並在

Query query = session.getNamedQuery("queryUserByAgeAndName");
query.setInteger("minAge", 25);
query.setString("likeName", "%a%");
List list = query.list();

Query接口的list()方法:
Query接口的list()方法用於取得一個List類的實例,此實例中包括的可能是一個對象集合,也可能是一個對象數組集合。最常見的使用是用list()方法來取得一組符合實例對象。如上示例。

Query接口的uniqueResult()方法:
當確信使用的HQL語句查詢時返回的集合中只有一個對象時,就可以使用這個方法。但如果返回結果中有多個對象,使用這個方法會拋出org.hibernate.NonUniqueResultException 異常,說“query did not return a unique result”。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章