2009-11-25 81 views
3

我已經寫了ChatComponent和其聊天消息之間的一個非常基本的和幼稚的一對多關係是這樣的:使jpa oneToMany關係有效嗎?

@OneToMany 
List<ChatMessage> chatMessages; 

這基本上工作,即做這樣的事情:

ChatMessage chatMessage = vo.toDomainObject(); 
chatMessage.setDate(new Date()); 
//Add the message to the chat component 
em.getTransaction().begin(); 
em.persist(chatMessage); 
chat.addChatMessage(chatMessage); 
em.persist(chat); 
em.getTransaction().commit(); 

能夠完成任務。只有在查看SQL日誌時,我可以看到每次聊天消息的整個集合都會再次持續。這顯然是我無法承受的事情,因爲聊天消息可能會迅速累計上千。

是被重複每個聊天消息的SQL如下:

Hibernate: insert into BaseComponent_ChatMessage (BaseComponent_id, chatMessages_id) values (?, ?) 

前面加:

Hibernate: delete from BaseComponent_ChatMessage where BaseComponent_id=? 

從此我的結論是Hibernate不有辦法知道我們不是處理一整套新的對象,而是應該保留已有的對象。

我敢肯定有一種方法可以添加(並堅持)只有一個成員關係的許多方面,但我似乎無法瞭解如何。

回答

1

覆蓋hashCodeequals您的ChatMessage類的方法,以便Hibernate可以知道這些是相同的對象。

使用您的IDE生成hashCode()和equals()。在Eclipse中,右鍵單擊> Source>生成hashCode並等於,然後爲您的實體選擇@Id的屬性。

此外,嘗試添加cascade=CascadeType.ALL屬性@OneToMany

+0

Hi Bozho, 確實很有道理。但是,我可以看到發佈的第一條語句是: Hibernate:從BaseComponent_ChatMessage中刪除BaseComponent_id =? ...這似乎表明它是ChatComponent(ChatComponent從此處繼承的BaseComponent),它不被識別爲已經存在。 我已經嘗試通過讓它返回實體的id在兩個類中實現hashCode()。我不確定這是怎麼走的,而且我對等號方法中該做什麼感到困惑。 然而,謝謝你,這絕對是一個很好的領導:-) – user162346 2009-11-25 10:14:41

+0

檢查我的更新 – Bozho 2009-11-25 10:17:11

+0

嗯,我已經嘗試了使用Eclipse生成hashCode和等於關係兩端的每種可能的組合,但我是仍然有n + 1插入:( 謝謝! – user162346 2009-11-25 10:28:03

2

我發現,避免聊天消息的完整列表,只有這樣才能每次都堅持是建立聊天組件和其聊天消息之間的雙向關係

@OneToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE}, fetch=FetchType.LAZY, mappedBy="parent") 
List<ChatMessage> chatMessages; 

@ManyToOne 
@JoinColumn(name="OWNER_CHAT_COMPONENT_ID", nullable=false) 
private ChatComponent parent; 

然後在addChatMessage功能我可以簡單地添加一個消息,聊天組件,而不必堅持它,然後堅持聊天組件和精美的作品。

em.getTransaction().begin(); 
    chat.addChatMessage(chatMessage); 
    em.persist(chat); 
    em.getTransaction().commit();