views:

17

answers:

1

Hi Buddies,

Here I have a question about persist many-to-many properties.

Example:

class Movie {
    /**
     * @hibernate.bag cascade="save-update" table="movie_genre"
     * @hibernate.collection-key column="ITEM_ID"
     * @hibernate.collection-many-to-many column="GENRE_ID" class="Genre"
     * @hibernate.collection-cache usage="read-write"
     */
    public List<Genre> getGenres() {
        return genres;
    }
...  
}

class Genre {
}

Supposed, there are two movies in db:
Movie A with Genre X1 & X2
Movie B with Genre Y1 & Y2

Now I am going to copy genres from Movie A to Movie B with the following code:

Movie b = findById('B');
Movie a = findById('A');
a.setGenres(b.getGenres());
session.saveOrUpdate(a);
session.flush();

Now, the relationship of original Movie B & genres are removed. But, if I refer to the following code:

a.setGenres(new ArrayList(b.getGenres()));

Then, the Movie B & genres relationship are kept.

In the first code snippet: hibernate will trigger two delete sql on relationship table movie_genre, which removing Movie B & A relationships;
In the second one: hibernate will trigger delete sql to remove Movie A only.

Is this the mechanism for Hibernate to persist relationship objects? Could you please give me some hints?

+1  A: 

The Genres list which Hibernates creates for you is not a simple java.util.LinkedList, it is connected to the Session and supports lazy-fetching, minimal puts and whatnot. In this case, it carries knowledge of its parent object and when you move it, it makes the undesired updates to the association table.

Instead, you should make the actual collection final, avoid setGenre() and instead of it, you should introduce "smarter" mutators, like addToGenre(Genre... genre), replaceGenres(List newGenres).

Hope this helps!

JesperSM
JesperSM, you are definitely right. The collecting list of Genres is an instance of org.hibernate.collection.PersistentBag, which carries the relationship, etc. Thanks a lot!
tom_tom