2011-11-07 191 views
1

雖然試圖對延遲加載做一些測試,爲了檢查我是否理解得很好,我完全困惑。混淆懶惰加載

下面是我使用我的測試實體:

@Entity 
public class Family { 
@Id 
private int id; 


@OneToMany(mappedBy="family", fetch=FetchType.LAZY) 
private Set<Person> members; 

//getters & setters 

public String toString(){ 
    String s=""; 
    for(Person p:getMembers()){ 
     s+=p.getFirstName(); 
    } 
    return s; 
} 
} 

@Entity 
public class Person implements Comparable<Person>{ 
@Id 
private int id; 

private String firstName; 
private String lastName; 

@ManyToOne 
private Family family; 

//getters &setters 
} 

這裏是我的主要方法:

public static void main(String[] args) { 
    factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME); 
    em = factory.createEntityManager(); 

    Query q = em.createQuery("select f from Family f"); 
    List<Family> families= q.getResultList(); 

    em.clear(); 
    em.close(); 
    factory.close(); 

    for(Family f:families){ 
     System.out.println(f); 
    } 
} 

我從延遲加載明白的是,如果一個屬性被標記爲被懶惰地取出,並且在被管理時沒有被訪問,它不會被加載到內存中,任何嘗試訪問它都不會工作。現在讓我困惑的是,即使在關閉EM和EMF後,通過分離的Family列表訪問懶惰成員屬性時,上述測試也沒有任何問題! ...這是正常的嗎?我是否理解懶惰加載概念?

注:我正在使用嵌入式數據庫的J2SE環境。我的提供商是EclipseLink的

由於提前
喬治

回答

2

檢查您的toString方法在工廠關閉之前未觸發,例如實體正在被記錄。我不建議在toString方法中觸發關係,因爲這很容易出錯,並且可能會意外觸發。打開EclipseLink日誌記錄可以幫助您瞭解工廠生命週期中的訪問位置,假設它不屬於問題的一部分。

+0

非常感謝您的幫助,我已經在[這裏](http: //www.eclipse.org/forums/index.php/mv/msg/261691/755570/#msg_755570):-) –

0

這可能是因爲使用延遲初始化JPA提供者不需要。對於JPA供應商來說這不是必須的要求,但是a hint

當指定FetchType.EAGER時,JPA需要急切地獲取數據,但當指定FetchType.LAZY時,不需要懶惰地獲取數據。

+0

感謝您的回答。我忘記說我的JPA提供者是EclipseLink,它支持延遲加載AFAIK。 –

2

確保您使用eclipselink代理或使用靜態編織。如果你不使用,那麼LAZY不會被編織,而且你會擁有EAGER。

另外EclipseLink支持在EntityManager關閉後訪問LAZY關係。 雖然沒有關閉工廠後。但是,如果對象位於緩存中,那麼它在關閉後也可以工作。另外,如果您在同一個持久性單元上打開了另一個工廠,那麼持久性單元仍處於打開狀態。

+0

我在[這裏](http://www.eclipse.org/forums/index.php/mv/tree/160098/#page_top)發現了一個類似的問題,並且有一個答案(作爲巧合發佈一個叫詹姆斯的成員也說:-)),他說:「實際上,編織只需要懶惰的OneToOne/ManyToOne懶惰會在OneToMany中無需編織就能工作。」,這在[here](http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#What_You_May_Need_to_Know_About_EclipseLink_JPA_Lazy_Loading)。 –

+0

關於在EntityManegr關閉後訪問LAZY關係的支持,我對此沒有任何問題,因爲我把這個理解爲一個優點...我只想確保如果我不訪問一個懶惰的關係它不會被加載到內存中,並且顯然這不會發生,因爲即使在關閉工廠之後(這在我的示例中嘗試它時是唯一的),但是家庭實例仍然能夠訪問他們的成員,並且如上所述,我在關閉工廠之前沒有訪問他們中的任何一個:( –