2013-04-28 40 views
1

我現在正在使用JPA-Hibernate,並希望集合爲空,直到我調用關聯的get()。我已經嘗試了好幾天,但沒有取得任何成功。 我想要這樣做的原因是因爲我使用Exterialize(或者Serialize),並且並不總是希望在將序列化字符串發送到客戶端時集合在那裏。JPA休眠希望懶加載返回空集合

@Entity 
public class Thread implements Externalizable { 
    static final long serialVersionUID = 9L; 


@OneToMany(mappedBy = "parentThread", fetch = FetchType.LAZY) 
    @LazyCollection(LazyCollectionOption.EXTRA) 
    public Collection<Reply> getReplies() { 
     return replies; 
    } 

這裏是回覆模式:

@Entity 
public class Reply implements Externalizable { 
    static final long serialVersionUID = 8L; 

    @ManyToOne 
    @JoinColumn(name = "threadId", referencedColumnName = "id", nullable = false) 
    public Thread getParentThread() { 
     return parentThread; 
    } 

此代碼是我用序列化模式:

public static final String serialize(Serializable object) throws IOException, ClassNotFoundException { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ObjectOutputStream oos = new ObjectOutputStream(baos); 
    oos.writeObject(object); 
    oos.close(); 
    BASE64Encoder base64Encoder = new BASE64Encoder(); 
    return new String(base64Encoder.encode(baos.toByteArray())); 
} 

這是我用它來找到線程對象

models.Thread thread = em.find(models.Thread.class, threadId); 

如果我使用entityMan ager.find()或一個查詢,它仍然加載回覆列表。所以要更加清楚,我希望收集在我生成實體時爲空。然後,如果我打電話get(),我希望它填滿。

下圖顯示答覆存儲在列表中。他們沒有任何價值,我認爲是因爲懶加載意味着他們是沒有真正從數據庫中獲取的代理實體?如果我錯了,請糾正。作爲一個側面說明,如果可以將列表存儲爲陣列列表或其他標準列表實現,那將是非常好的。我知道JPA需要persistentBag/persistentSet符號,因爲它們可以具有標準實現不允許的重複值以及可能的其他原因。但是,爲了將模型序列化到客戶端,不需要這些庫是很棒的,而且它們似乎也不適用於android,因爲在使用android時,SSID似乎在庫中發生了變化。

Image with returned replies

我真的希望這是可能的。 Thx提前!

+0

你使用什麼機制來序列化你通過線路發送的實體,你確定它們是在你調用find時獲取的,或者可能是在序列化時。 – cproinger 2013-04-28 22:18:16

+0

你好!我用更多的信息填充了這個問題。我100%肯定它是在find(),因爲當我測試時,我使用調試器來停止並在調用find()後檢查內容。即使我發佈我的序列化「機制」,如果它可以幫助某種方式。我已經做出了一個解決方法,只要該集合正在懶惰地加載,並且由於某種原因不起作用,就應該可以工作。這是一個鏈接到這個問題,如果那個更加可以解決: http://stackoverflow.com/questions/16294572/jpa-hibernate-collections-not-lazily-loaded – 2013-04-30 07:44:12

+0

有可能調試器觸發負載當它想要顯示其大小的集合?更可靠的方法是在不序列化任何內容並捕獲數據庫查詢的wireshark trace時進行測試。根據JPA規範,延遲加載是可選的,但是我已經在Hibernate中進行了測試,並且它可以工作,在Eclipselink中只有在啓用加載時織入時才起作用。 – German 2013-04-30 14:35:32

回答

0

我絆了這個博客:https://sites.google.com/a/pintailconsultingllc.com/java/hibernate-extra-lazy-collection-fetching

  1. 我不知道如果LazyCollectionOption.EXTRA是適合你在這種情況下,打開你的SQL日誌,看看真正執行哪些查詢通過休眠
  2. 您註釋了一個Collection getter,所以這可能適用於您(來自引用的博客)如果類是org.hibernate.collection.PersistentBag,那麼您使用的是bag語義,現在collection將會加載所有的您第一次觸摸列表中的任何項目時的項目。
  3. 我不會在場景中有可能是客戶端和服務器在不同的時間(機器人類版本與服務器類版本)升級,使用ObjectOutputStream。如果您序列化爲xml或json,那麼您將爲這些類型的問題安全處理很多麻煩。例如,使用xstream(不要使用默認的xstream-xml序列化,因爲它包含整個類名,使用別名),您可以告訴序列化程序在序列化之前通過註釋或顯式忽略哪些字段。