2012-03-29 96 views
2

我有一個關於訪問模型對象的成員變量的簡單問題。Scala模板訪問Play 2.0中的模型對象屬性

我有以下的模型對象:

@Entity 
public class Person extends Model{ 
    @Id 
    public Long id; 
    public String name; 
} 

@Entity 
public class Account extends Model{ 
    @Id 
    public String email; 
    public String password; 
    @OneToOne 
    public Person person; 
} 

到目前爲止好,任何給定person可以有一個account。從zentask示例複製Account對象。認證後,我重定向到顯示用戶真實名稱的索引頁面,如Person.name成員變量中所述。該Account對象插入到頁面一樣,象這樣的zentasks例如:

Account.find.byId(Controller.request().username()); 

現在下面的怪事在模板發生,我不明白:

@account.person.name 

導致Null值在調用時插入到模板中:

@account.person.getName() or @account.person.getName 

結果如預期的那樣從person對象插入了正確的名稱。

@account.person 

顯示人物對象的.toString(),也正確顯示名稱。

所以總結一下:上面的代碼有什麼問題?爲什麼我可以在沒有任何問題的情況下調用account.person值,但是當我調用account.person.name時,這不起作用了

提前致謝!

理查德

回答

3

這是因爲JPA使用方面攔截的getter使用和從懶加載對象填充中的丟失數據。我不知道傳統思維是什麼,但我不會因爲這個原因而使用JPA的公共成員,它會一直打破框架。

如果你真的想使用公共的成員,你必須標記爲預先抓取的關係:

@OneToMany(fetch=FetchType.EAGER) 

或明確地獲取所有對象樹,你需要在你的模板(啊)的。

就你的情況而言,OneToOne定義在關係的另一端,如果你在Account端定義它,它應該默認提取eager。我忘了你是否可以在兩個實體上定義OneToOne,我認爲你可以,但你可能不得不擺弄一下。

總的來說,不要使用JPA的公共成員,它會破壞。更好的是,消除JPA並使用Anorm代替它,它比JPA更成功映射到問題域。像這樣的問題一直導致JPA實現佔用任何人似乎能夠預測的實施時間的兩倍。

+0

嗨PlexQ!感謝您的迴應! 這種行爲很奇怪,與Play一樣!鼓勵你在課堂上使用公共成員。我看到JPA(在我的情況下,Ebean是Play!2.0中的默認設置)如何使用Aspects來執行延遲加載。但有人可能會認爲這是如上所述的工作。再次感謝!我將獎勵給你,因爲看來我不會從社區那裏得到關於此的完整答案。 – Bjarne77 2012-04-02 09:29:26

+0

另一個想法浮現在腦海中:我不知道使用靜態編織是否會改善這一點,而不是加載時間編織?我可以發誓我記得可以指向剪切字段訪問,只是JPA實現我用過似乎沒有。您使用哪種JPA提供程序? – PlexQ 2012-04-03 14:10:22

+0

EBean實現作爲默認ORM提供程序與Play! 2.0框架。我直到Play才聽到!隨它而來。 – Bjarne77 2012-04-03 14:17:02

0

因爲延遲加載在字段中的值,當你從類本身訪問它們只得到加載的(東西,在正常情況下會使用一個setter /吸氣

爲了加載你乙醚值必須寫getter和setter 或者你可以創建檢查每一個值梅索德

您可以在以下梅索德添加到您的帳戶實體:。

public void checker(){ 

    if(email==null){} 
    if(password==null){} 
    if(person==null){} 
} 

這將加載每個VALU e,但不會降低性能