March 28, 2013

Hibernate strong versus weak relationship

The problem

When you want to map two entities together using a many-to-many connection, Hibernate needs you to provide a @ManyToMany JPA annotation. When I wanted to connect two entities I initially set up the connection in the following way:

@Table(name = "person")
public class Person extends AbstractDocumentEntity {

    @ManyToMany(mappedBy = "persons")
    private List<PersonGroup> groups;

And the corresponding group entity looks like this:

@Table(name = "person_group")
public class PersonGroup extends AbstractTrackedEntity {

    @ManyToMany
    @JoinTable(name = "person_person_group",
            joinColumns = { @JoinColumn(name = "group_id") },
            inverseJoinColumns = { @JoinColumn(name = "person_id") })
    private List<Person> persons;

This setup works perfectly when you try to read data from the database. Whenever you fetch the base entity, you can also read its connected groups or persons. So far, so good.

The problem lies however in the situation where you want to update the list of connected entities. In its current state, no changes are saved no matter if I add new entities to either of the collections.

Cascading changes

The first change that needed to be done, was to define that changes to the collection should be updated when the main enity gets persisted. One defines this by saying that the collection changes should be cascaded from the main entity. This is defined by adding a cascade property to the connection definition:

    @ManyToMany(mappedBy = "persons", cascade = CascadeType.ALL)
    @ManyToMany(cascade = CascadeType.ALL)

This changed the situation somewhat when I tried to update the collections. When I added entities to the groups collection from the person entity, nothing seemed to happen when I told Hibernate to persist the changes. When I added persons from the group entity, changes were saved. This shows that the cascade property is ignored when you are also using the mappedBy property.

Weak versus strong connection

The problem lies in how Hibernate defines this connection between these two entities. The group entity owns the connection in this case, as it defines what table and fields to use when looking up data. The person entity simply connects to this connection without defining what the connection entails. In this case this means that the connection from the group entity is the strong side, while the connection from the person side is the weak side. What this means in practice, is that no changes will be saved from the weak side, no matter if you define the connection to cascade its changes or not.

The solution to all of this is to define both sides as the strong side, by adding full definition on both ends, and drop the mappedBy property:

@Table(name = "person")
public class Person extends AbstractDocumentEntity {

    @OrderBy("title")
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "person_person_group",
              joinColumns = { @JoinColumn(name = "person_id") },
              inverseJoinColumns = { @JoinColumn(name = "group_id") })
    private List<PersonGroup> groups;

And the group entity ended up looking like this:

@Table(name = "person_group")
public class PersonGroup extends AbstractTrackedEntity {

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "person_person_group",
               joinColumns = { @JoinColumn(name = "group_id") },
               inverseJoinColumns = { @JoinColumn(name = "person_id") })
    private List<Person> persons;

As a bonus I also added a sort definition from the person entity to make the returned result look better in the application interface.

Final thoughts

The end result is a slightly more convoluted configuration. For me there is no logical reason why the original solution with a cascade property added should not work. I would rather that Hibernate read the cascade property, and from there decide what should be done with the collection, no matter if you use mappedBy or not.

6 comments:

  1. شركة الطيار تعتبر افضل نقوم بتنظيف الشقق و الفلل بمدينة الدمام بافضل المكينات و الطرق الحديثة حيث اننا كما اننا نعتبر افضل شركة شركة كشف تسربات المياه بالرياض
    نقوم بتنظيف الشقق من الداخل جزء جزء علكم ان تتصلو علي شركة الطيار باسرع وقت ممكن لاننا افضل يمكنك معرفة المزيد حول الخدمة شركة كشف تسربات المياه بالاحساء

    ReplyDelete



  2. [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] نشتري الاثاث المستعمل بجدة [/URL]
    [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] نشتري الاثاث المستعمل بمكة [/URL]
    [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] شراء الاثاث المستعمل بجدة [/URL]
    [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] شراء الاثاث المستعمل بمكة [/URL]
    [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] ارقام شراء الاثاث المستعمل بجدة [/URL]
    [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] ارقام شراء الاثاث المستعمل بمكة [/URL]
    [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] ارقام محلات شراء الاثاث المستعمل بجدة [/URL]
    [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] شراء اثاث مستعمل بجدة [/URL]
    [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] شراء اثاث مستعمل جدة [/URL]
    [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] شركات شراء اثاث مستعمل في جدة [/URL]
    [URL="http://fcnsc.com/used-furniture-in-jed-and-mec//"] شراء الاثاث المستعمل بمكة المكرمة [/URL]

    [URL="http://fcnsc.net/p651//"]محلات الاثاث المستعمل بالمدينة المنورة[/URL]
    [URL="http://fcnsc.net/p651//"]ارقام الاثاث المستعمل بالمدينة المنورة [/URL]
    [URL="http://fcnsc.net/p651//"]حقين الاثاث المستعمل بالمدينة المنورة [/URL]
    [URL="http://fcnsc.net/p651//"]شراء الاثاث المستعمل بالمدينة المنورة [/URL]
    [URL="http://fcnsc.net/p651//"]شراء اثاث مستعمل بالمدينة المنورة[/URL]

    ReplyDelete