سؤال

Here's an excerpt of the official Hibernate tutorial

First, keep in mind that Hibernate does not affect normal Java semantics. How did we create a link between a Person and an Event in the unidirectional example? You add an instance of Event to the collection of event references, of an instance of Person. If you want to make this link bi-directional, you have to do the same on the other side by adding a Person reference to the collection in an Event. This process of "setting the link on both sides" is absolutely necessary with bi-directional links.

Many developers program defensively and create link management methods to correctly set both sides (for example, in Person):

protected Set getEvents() {
    return events;
}

protected void setEvents(Set events) {
    this.events = events;
}

public void addToEvent(Event event) {
    this.getEvents().add(event);
    event.getParticipants().add(this);
}

public void removeFromEvent(Event event) {
    this.getEvents().remove(event);
    event.getParticipants().remove(this);
}

What does the word "absolutely" mean in this case? :

  • Meaning it's recommended in order to keep the relationship consistent as long as the current logic process finishes, but persistence obviously can occur ?
  • Meaning that without setting the other side (not owning the relationship), the persistence can strictly not be made ?

In other words, what would happen if my "adding" method is:

public void addToEvent(Event event) {
    this.getEvents().add(event);
    //event.getParticipants().add(this); without this line
} 
هل كانت مفيدة؟

المحلول 3

It means that the in-memory copies of both data structures aren't automatically updated when you add one side of a relationship, so that while your code is using the Java proxies for the database rows, you might add an event to a participant's event list, but the event wouldn't show the participant, and any code that was (reasonably) relying on the two being in sync would fail. This is an obnoxious pitfall in JPA, but it isn't Hibernate-specific and doesn't appear to be going away any time soon.

نصائح أخرى

A bi-directional relationship allows both entities participating in the relationship to obtain the entities on the other side of the relationship. When you insert these entities participating in a bi-directional relationship you are responsible for managing both sides of the relationship.

In the participant/event relationship you have presented this is done by setting the appropriate entities on both sides of the relationship.

So if you are attempting to add an event for a participant, the event must be added to the participants Collection<Event> and the participant must be added to the event's Collection<Participant>. You cannot simply add the event to the participant's Collection<Event> and expect hibernate to populate the Participant in the event's Collection<Participant>.

If you fail to add the Participant to the Collection<Participant> for an event the Collection<Participant> will be out of synch with the database and may fail to insert depending on the established constraints and cascade setting.

As other answers have pointed out, hibernate does not break normal Java semantics. Adding a participant to the collection on the event does not transparently add the event to the collection on the participant. You are responsible for setting it.

According to the docs (not the tutorial):

Changes made only to the inverse end of the association are not persisted. ... The non-inverse side is used to save the in-memory representation to the database.

In this is the code example straight from the docs Item is the inverse side of the association:

category.getItems().add(item);          // The category now "knows" about the relationship
item.getCategories().add(category);     // The item now "knows" about the relationship

session.persist(item);                   // The relationship won't be saved!
session.persist(category);               // The relationship will be saved

In summary, from my reading of the docs it is not absolutely necessary, but failing to add the inverse-side entity to the collection on the non-inverse-side will cause the relationship to not be saved.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top