making a jpa oneToMany relationship effective?
I have written a very basic and naive oneToMany relationship between a ChatComponent and its Chat Messages like this:
@OneToMany
List<ChatMessage> chatMessages;
This basically works, i.e., doing something like:
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();
gets the job done. Only, looking at the SQL logs, I can see that every time, the entire collection of chat messages is persisted again. That's obviously something I can't afford, given chat messages could quickly add up in the thousands.
The SQL that gets repeated for each chat message is as follows:
Hibernate: insert into BaseComponent_ChatMessage (BaseComponent_id, chatMessages_id) values (?, ?)
preceded by:
Hibernate: delete from BaseComponent_ChatMessage where BaseComponent_id=?
From this I conclude that Hibernate doesn't have a way to know that we're not dealing with a whole set of new objects and that it should keep those it already has.
I'm sure there is a way to add (and persist) only one member of the many side of a relationship, but I can't seem to find o开发者_Go百科ut how.
I found that the only way to avoid the entire list of chat messages to be persisted each time is to establish a bidirectional relationship between the chat component and its chat messages
@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;
then in the addChatMessage function I can simply add a message to the chat component without having to persist it, then persist the chat component and that works beautifully.
em.getTransaction().begin();
chat.addChatMessage(chatMessage);
em.persist(chat);
em.getTransaction().commit();
Override hashCode
and equals
methods of your ChatMessage
class, so that Hibernate can know that these are the same objects.
Use your IDE to generate hashCode() and equals(). In Eclipse it is right click > Source > Generate hashCode and equals, and choose the property which is @Id
for your entity.
Also, try adding the cascade=CascadeType.ALL
attribute to @OneToMany
精彩评论