2017-02-19 55 views
2

我很難理解懶惰抓取,因爲我不工作,因爲我在書中讀到它,他們說在懶惰抓取jpa只會在它們被訪問時加載實體通過geters,所以我創建了一個Arquillian項目來測試這個概念,但它不起作用。 這裏有我的兩個實體爲什麼懶惰抓取不起作用JPA

package com.actionbazaar.model; 

@Entity 
@TableGenerator(
     initialValue = 5, 
     name = "PERSON_SEQ", 
     table = "PERSON_SEQ_TABLE", 
     pkColumnName = "SEQ_NAME", 
     pkColumnValue = "PERSON", 
     valueColumnName = "SEQ_VALUE") 
public class Person implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id; 

    private String fname; 
    private String lname; 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "owner", cascade = CascadeType.PERSIST) 
    List<Address> addresses; 
    //getters and setters 
} 

地址

@Entity 
public class Address implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id; 
    private String city; 
    private String zip; 
    private String street; 

    @ManyToOne 
    private Person owner; 
//getters and setters 
} 

我有一個無狀態會話bean用這種方法

public Person getFirstPerson() { 
    Person p = em.find(Person.class, 1); 
    em.detach(p); 
    //why this call does not create an exception 
    p.getAddresses().get(0); 
    return p; 
} 

因爲我在訪問地址之前分離了實體,所以地址列表應該是空的,當我把它分開時,它不再由entitymanager管理,所以我不應該得到該地址的人 問題是我可以獲取地址的人,即使我懶惰地址字段獲取和分離實體之前accessinbg地址字段! 請一定說明一下。

的其他測試

Person p= myStatlessSessionBean.getFirstPerson(); 
myOtherStalessSesionBean.moveAllPeopleToCity("NY"); 
if(p.getAddresses().get(0).getCity().equals("NY")) 
{ 
    system.out.prinln("person moved"); 
} 
else { 
system.out.prinln("person did not move"); 
} //prompts person did not move 

回答

4

是的,哥們,你是對的。你在這裏沒有做錯任何事。我剛纔打開的臨JPA 2,第2版圖書,發現這個:

here is the snapshot

您正在使用與GlassFish嵌入式這實際上是造成問題的原因。你的代碼沒有問題。正如上面提到的這本書的作者,提到

一些供應商可能 試圖解決的關係,而其他人可能只是拋出一個異常,或留下未初始化的屬性。

因此,在你的情況下,關係解決而不是延遲加載。只需使用其他供應商實施相同的示例,您就不會遇到任何問題。這裏使用glassfish-embedded,lazyfetch不起作用。否則應拋出異常,因爲變量p已分離。

這裏是link這裏我也看了這個美麗的資料片

這裏是快照從上面的鏈接snapshot

+0

是的..你是對的..我很想知道爲什麼發生這件事。獲得更多信息。謝謝@achabahe –

+1

@achabahe我懷疑這是原因,但是你用「hibernate」標記了你的問題,雖然它似乎沒有使用它。這是誤導。 –

+0

可能是他試圖達到冬眠認識的人:D? @JBNizet^_^ –

1

你只分離父實體,人。您並未分離子實體Addresses,並且當您獲取地址時,它指的是仍由持久性上下文管理的實體。

如果你想讓孩子也被分離,你應該使用CascadeType.DETACH。

你可能會說,「但我的FetchType設置爲LAZY!」。僅僅因爲它是懶惰的,並不意味着該對象爲空。 Hibernate返回代理對象的集合類型,一旦你嘗試訪問它們,它將填充它們的值。

+0

如何對第二個測試!,我已經改變了級聯添加CascadeType.DETACH,但仍然是同樣的問題,首先我想知道如果理解正確的概念和我期待的行爲是正確的 – achabahe

+1

我同意@塔希爾。根據JPA規範:「當需要跨供應商的互操作性時,應用程序不得使用延遲加載。」 JPA規範還提到LAZY獲取僅僅是一個提示,並告訴我它的實現由供應商決定。 – raminr