1. 程式人生 > >Hibernate的延遲載入

Hibernate的延遲載入

hibernate中,延遲載入大致可以分為兩類,一類是延遲屬性載入,另一類是延遲關聯實體載入。

普通屬性:分兩種情況,一種是集合屬性,一種是非集合屬性(如String、Integer......)

集合屬性的延遲載入通過PersistentSet、 PersistentList、PersistentBag、PersistentMap、PersistentSortedMap、PersistentSortedSet作為代理類來實現,代理類中儲存了session以及owner屬性,owner屬性表示了集合屬性所屬的one側的實體。

非集合類屬性的延遲載入相對比較複雜。僅通過@Basic(fetch = FetchType.LAZY)註解是無法實現延遲載入的。需要讓實體實現FieldHandled介面,宣告FieldHandler屬性,通過攔截器原理注入對應的FieldHandler屬性,起到類似於上述代理類的作用,FieldHandler同樣也保持了session,以及需要延遲載入的屬性。

@Basic(fetch = FetchType.LAZY)
@Column(name="CONTENT")
public String getContent() {
    if (fieldHandler != null) {
        return (byte[]) fieldHandler.readObject(this, "content", content);
    }
    return null;
}
public void setContent(byte[] content) {
    this.content = content;
}
@Override
public void setFieldHandler(FieldHandler handler) {
    this.fieldHandler = handler;
}
@Override
public FieldHandler getFieldHandler() {
    return this.fieldHandler;
}
Hibernate官網對非結合屬性的延遲載入有如下的評論:

Lazy property loading requires buildtime bytecode instrumentation. If your persistent classes are not enhanced, Hibernate will ignore lazy property settings and return to immediate fetching.

A different way of avoiding unnecessary column reads, at least for read-only transactions, is to use the projection features of HQL or Criteria queries. This avoids the need for buildtime bytecode processing and is certainly a preferred solution.

大致的意思就是:應該是因為,我們並未用到編譯時位元組碼增強技術的原因。如果只對部分property進行延遲載入的話,hibernate還提供了另外的方式,也是更為推薦的方式,即HQL或者條件查詢。

更為推薦的方式說白了就是在查詢的時候就過濾掉不需要的屬性,以下列出HQL和Criterial的兩種實現方法:

// criterial實現
criteria.setProjection(
                Projections.projectionList().add(Projections.property("id"), "id")
                        .add(Projections.property("age"), "age")).setResultTransformer(
                Transformers.aliasToBean(User.class));

// HQL實現
Query query = session.createQuery("select u.id as id,u.age as age from User u where u.id=2");
query.setResultTransformer(Transformers.aliasToBean(User.class));

關聯實體:分兩種情況,一種是多對一,另一種是一對一。

關聯實體是多個實體時(包括一對多、多對多):此時關聯實體將以集合的形式存在,Hibernate 將使用 PersistentSet、PersistentList、PersistentMap、PersistentSortedMap、PersistentSortedSet 等集合來管理延遲載入的實體。這就是前面所介紹的情形。

關聯實體是單個實體時(包括一對一、多對一):當 Hibernate 載入某個實體時,延遲的關聯實體將是一個動態生成代理物件。Hibernate 使用 Javassist 專案動態生成的代理類——當 Hibernate 延遲載入關聯實體時,將會採用 Javassist 生成一個動態代理物件,這個代理物件將負責代理“暫未載入”的關聯實體。但是在一對一關係中,延遲載入是有陷阱的。

一對一關聯一般有兩種形式,一種是主鍵關聯;另一種是外來鍵關聯。

主鍵關聯:

Husband:id,name
Wife:id,name

Husband實體:
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
@PrimaryKeyJoinColumn
getWife()
@GenericGenerator(name = "Wife", strategy = "foreign", parameters = { @Parameter(name = "property", value = "husband") })
Wife實體:
@OneToOne(mappedBy = "wife", fetch = FetchType.LAZY)
getHusband()
以上是hibernate中的配置。其中“optional=false”的配置時關鍵,否則即使配置了fetch策略為lazy,也無法做到在獲取husband實體的時候延遲載入wife實體。optional的預設值是true,表示關聯的實體可以為null。在一對一的延遲載入中,hibernate並非一定對需要延遲載入的實體生成一個動態代理物件,而是當被關聯的實體確定不為null時,才會生成,否則直接將其置為null。所以問題就來了,對於兩個通過主鍵關聯的一對一實體,在獲取到其中一個實體後,要判斷與之關聯的實體是否存在,則必須要再查詢一次資料庫才可以。這也就是為什麼在設定了延遲載入策略後,hibernate還是立即傳送了一次查詢請求給資料庫。

要解決一對一關係中的延遲載入,共有兩種方法:一種就是上面提到的,把optional設定為false,即關聯的實體一定不為null。這樣一來,hibernate就會立即為配置延遲載入的實體生成一個動態代理類。

第二種方法就是通過外來鍵來關聯,即:

Husband:id,name, wife_id
Wife:id,name
其中husband_id與Husbande中的id關聯
Husband實體:
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "wife_id", , referencedColumnName = "id")
getWife()
Wife實體:
@OneToOne(mappedBy = "wife", fetch = FetchType.LAZY)
getHusband()
這樣一來,直接可以通過husband中的wife_id的null與否來判斷wife實體是否為null。


相關推薦

Hibernate延遲載入(查詢優化),關聯級別延遲載入優化策略

1. 類級別延遲載入: 類級別使用延時載入,可以在class標籤上修改是否使用延遲載入 <class name="com.ssh.domain.Customer" table="cst_customer"> 2 關聯級別延遲載入:預設使用到的時候才進行查詢()

hibernate延遲載入和session關閉問題

1.關閉延遲載入特性 2.在session關閉之前先獲取需要查詢的資料,可以使用工具方法Hibernate.isInitialized()判斷物件是否被載入,如果沒有被載入則可以使用Hibernate.initialize()方法載入物件。 使用攔截器或過濾器延長Session的生命週期直到

hibernate延遲載入(get和load的區別)

在hibernate中我們知道如果要從資料庫中得到一個物件,通常有兩種方式,一種是通過session.get()方法,另一種就是通過session.load()方法,然後其實這兩種方法在獲得一個實體物件時是有區別的,在查詢效能上兩者是不同的。 一.load載入方式 當使用

7.Hibernate 延遲載入&立即載入

延遲載入的好處 1.降低了記憶體的開銷,在用到某些資料的時候才會到資料中進行查詢。 2.提高了程式執行效能。 注:如果session被關閉了,而你又想用到某些資料,這個時候使用延遲載入會出錯;需要立即

hibernate 延遲載入 load和get方法

延遲載入 延遲載入: 當hibernate從資料庫中載入某個物件時,不載入關聯的物件,而只是生成了代理物件。使用session中的load的方法(在沒有改變lazy屬性,屬性值為true的情況下)獲取到的也是代理物件。 立即載入: 當Hibernat

hibernate延遲載入以及no-session

延遲載入:延遲載入(lazy load懶載入)是當在真正需要資料時,才執行SQL語句進行查詢,避免了無謂的效能開銷。  延遲載入分類:  01.類級別的查詢策略  02.一對多和多對多關聯的查詢策略  03.多對一關聯的查詢策略 類級別的查詢策略      1.類級別

Hibernate延遲載入問題

  Hibernate延遲載入是專案中非常常用的技術。通過使用Hibernate延遲載入機制可以在載入資料是不必載入全部資料,而是隻載入我們需要的那部分,其餘部分在需要使用時才從資料庫裝載,以此來減少資

hibernate延遲載入(load、get區別)

由於Spring控制的Hibernate的生命週期只針對資料層和服務層,而未管理到表現層,所以在表現層使用延時載入會出現the owning Session was closed或者no session or session was closed的異常資訊。針對這一點,可以通

SSH整合——Hibernate延遲載入引發的問題

這裡就是因為一開始載入Employee集合的時候,因為department屬性未被使用,所以採用了延遲載入。當在jsp頁面遍歷Employee集合的時候,此時就用到了department屬性,但是因為這裡採用的是getHibernateTemplate(),

hibernate 延遲載入與動態代理

Hibernae 的延遲載入是一個非常常用的技術,實體的集合屬性預設會被延遲載入,實體所關聯的實體預設也會被延遲載入。Hibernate 通過這種延遲載入來降低系統的記憶體開銷,從而保證 Hibernate 的執行效能。 下面先來剖析 Hibernate 延遲載入的“祕

hibernate延遲載入

在hibernate中我們知道如果要從資料庫中得到一個物件,通常有兩種方式,一種是通過session.get()方法,另一種就是通過session.load()方法,然後其實這兩種方法在獲得一個實體物件時是有區別的,在查詢效能上兩者是不同的。 一.load載入方式 當使用load方法來得到一個物件時,

hibernate延遲載入機制——get和load原理

在hibernate中我們知道如果要從資料庫中得到一個物件,通常有兩種方式,一種是通過session.get()方法,另一種就是通過session.load()方法,然後其實這兩種方法在獲得一個實體物件時是有區別的,在查詢效能上兩者是不同的。 一.load載入方式 當

hibernate之4.延遲載入

pop not in 異常 .get pos pan 實體對象 content except 延遲載入: 僅僅有當使用以實體對象的屬性(除主鍵屬性外)時,才會發送查詢語句到數據庫 get不支持延遲載入 @Test public void getTes

Hibernate延遲載入機制&&在實際應用中,延遲載入與Session關閉的矛盾是如何處理的?

Hibernate的延遲載入機制&&在實際應用中,延遲載入與Session關閉的矛盾是如何處理的? 延遲載入就是並不是在讀取的時候就把資料載入進來,而是等到使用時再載入。Hibernate使用了虛擬代理機制實現延遲載入,我們使用Session的load()方法載

Hibernate之關係延遲載入(json死迴圈問題的解決方法)

問題 在SSH框架對一些一對多,多對多關聯關係的資料做分頁查詢的時候,出現了死迴圈的狀態 原因(你中有我,我中有你) 原因在於你要轉化的物件裡配置了對另外一個物件的關聯,而那個物件裡又配置了對你這個物件的關聯。比如我的兩個類叫Shop(商店)和Staff(員工),一個商店可以有多個員工,

Hibernate(二)一級快取、延遲載入

一級快取概念: 一級快取又稱為session級別的快取,所以當session關閉時一級快取也會關閉。如果每次查詢或修改資料都到資料庫中進行查詢或修改,當資料量比較大時就會對程式的效能產生比較大的影響。而一級快取正好解決了這一問題。每次對資料進行查詢時先到快取中去查詢所需要的

Hibernate載入策略(延遲載入與即時載入)和抓取策略(fetch)

假設現在有Book和Category兩張表,表的關係為雙向的一對多,表結構如下: 假設現在我想查詢id為2的那本書的書名,使用session.get(...)方法: Session session=HibernateUtil.getSession(); Book

Hibernate是如何延遲載入

Hibernate是如何延遲載入的 (1)首先介紹一下延遲載入的幾種情況: 當呼叫Session上的load()方法載入實體時,就會採用延遲載入 當Session載入某個實體時,會對這個實體中的集合屬性值採用延遲載入   當Session載入某個實體時,

hibernate 普通欄位延遲載入無效的解決辦法

關聯物件的延遲載入就不說了,大家都知道。 關於普通欄位的延遲載入,尤其是lob欄位,若沒有延遲載入,對效能影響極大。然而簡單的使用 @Basic(fetch = FetchType.LAZY) 註解並沒有效果。hibernate對此的解釋是Lazy property lo

hibernate的級聯、延遲載入、inverse屬性

          hibernate的級聯是用來說明資料庫中二個表之間的相互關係(one---to ---one, one ---to---many, many---to---many)。當對主物件做某種操作時,是否對其相關聯的子物件也做相對應的操作。 常見的級聯(cas