2

I am relatively new to Hibernate so I am still finding hard to understand a few concepts. And one of them is the owning.

I have a relationship between 2 objects.

Conversation

@OneToMany(mappedBy = "conversation", cascade = CascadeType.ALL)
private List<ConversationParticipant> participants;

ConversationParticipant

@ManyToOne
@JoinColumn(name = "ConversationID")
private Conversation conversation;

What I want to achieve is that when someone removes the participant from the list of the participants and update object conversation this casscades and removes the ConversationParticipant entry from the db.

Is my mapping wrong for this. The code runs find, it removes everything that it is suppose to and then it updates the Conversation object, however the participants are still there after refreshing the page.

Any ideas? Suggestions

Boris Horvat
  • 563
  • 2
  • 13
  • 28

1 Answers1

3

To delete something from the database, delete() must be called:

Conversation c = session.get(Conversation.class, conversationId);
for (Iterator<ConversationParticipant> it = c.getParticipants().iterator(); it.hasNext(); ) {
    Participant p = it.next();
    it.remove(); // Hibernate doesn't care: you've removed an element from a collection
                 // which is not the owner side

    p.setConversation(null); // Hibernate will set the foreign key in the participant 
                             // to NULL, since you modified the owning side

    session.delete(p); // Hibernate will remove the row from the participant table
}

An exception to this rule is when orphanRemoval = true is set on the OneToMany association. In this case, removing the participant from the collection of participants will remove it from the database:

@OneToMany(mappedBy = "conversation", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ConversationParticipant> participants;

...

Conversation c = session.get(Conversation.class, conversationId);
for (Iterator<ConversationParticipant> it = c.getParticipants().iterator(); it.hasNext(); ) {
    Participant p = it.next();
    it.remove(); // Hibernate will remove the participant from the database,
                 // because orphanRemoval is set to true
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Just to clarify.Lets say that I change the ownership and now the Conversation is the owner of the relationship. If I remove element from the list, will this remove it from the db, or will it only break the relationship and Conversation wont have this participant anymore? – Boris Horvat Dec 26 '12 at 13:45
  • It will only break the relationship. Being the owner of the association only means: "Hibernate looks up this side to know which association exist between the entities. The other side is ignored." – JB Nizet Dec 26 '12 at 13:48
  • Ok i see now. tnx for the clarification – Boris Horvat Dec 26 '12 at 13:53
  • I just thought of something else. What does cascade do then? What would happen if I would to set conversation to null in participant and then updated the conversation. Would the cascade trigger the update? And if I have orphaneRemovel set to true would then this removed it from the db? tnx again for help – Boris Horvat Dec 26 '12 at 13:57
  • I guess that cascading would only happen from the owning side to the non owning side – Boris Horvat Dec 26 '12 at 14:01
  • cascade cascades operation. If you call `session.merge()` with a conversation as argument, Hibernate will also `merge()` all the participants in its list when cascade is set to MERGE (or ALL, obviously). Same for the other operations. Note that if you work with attached entities, modifying an entity will transparently persist the modification in database, without any need to call a method on the session. And no, cascading goes from one entity to another, without caring which is the owner. Re-read what I said about what being the owner means. It doesn't mean anything else. – JB Nizet Dec 26 '12 at 14:01