views:

282

answers:

2

I have two tables with the many-to-many association.

— DB fragment:

loads
Id
Name

sessions
Id
Date

sessionsloads
LoadId
SessionId

— Hibernate mapping fragments:

/* loads.hbm.xml */
<set name="sessions" table="sessionsloads" inverse="true">
    <key column="LoadId" />
    <many-to-many column="SessionId" class="Session" />
</set>
…
/* sessions.hbm.xml */
<set name="loads" table="sessionsloads">
    <key column="SessionId" />
    <many-to-many column="LoadId" class="Load" />
</set>

In order to remove one entry from the association table sessionsloads, I execute this code:

Session session = sessionDao.getObject(sessionId);
Load load = loadDao.getObject(loadId);

load.getSessions().remove(session);
loadDao.saveObject(load);

But, after launching, this code change nothing.

What's the right way to remove an association?

+1  A: 

Looks like you just need to turn on Transitive persistence (e.g., cascade=all-delete-orphan for "full" transitive.)

-- Edit Thanks for the upvote, althugh Pascal was accurate in that cascade alone is not enough to fix the original problem, but that both sides of the relationship weren't being managed. Teach me to answer hastily :)

--

Also, an Entity named Session broke my brain :(

Affe
Anyway, thanks you. Actually, upvoted for the `Session`. Agreed as it's totally unsuitable name. But can't change it at present.
Bar
+3  A: 

You need to update both sides of the link between Load and Session:

Session session = sessionDao.getObject(sessionId);
Load load = loadDao.getObject(loadId);

load.getSessions().remove(session);
session.getLoads().remove(load);
loadDao.saveObject(load);

Actually, many developer use defensive methods to manage bi-directional associations. For example on Load, you could add the following methods:

public void removeFromSessions(Session session) {
    this.getSessions().remove(session);
    session.getLoads().remove(this);
}
public void addToSessions(Session session) {
    this.getSessions().add(session);
    session.getLoads().add(this);
}
Pascal Thivent
Thanks, tried that, but does not work too. Hibernate even does not write any `delete` query to the log.
Bar
@Bar There must be another problem somewhere because this definitely works. I'll try to reproduce later with your mapping but I know it's working.
Pascal Thivent
As you mentioned, `cascade` does not work in this case, right? Also, people say it can work with the `session.flush()`. But what can I do if I use `getHibenateTemplate`?
Bar
You are right, the problem were in another place — my fault with the `compareTo()` function. Thank you!
Bar
@Pascal Am I right if I consider that omitting `inverse="true"` attribute will cause using this line `sessuibDao.saveObject(session);` too?
Bar
@Bar If you omit the `inverse="true"`, then you won't have a bi-directional association but 2 uni-directional associations (this is very different). And in that case, yes, I believe you'd have to save the `session` entity too.
Pascal Thivent
Thanks! I finally get it.
Bar