Problem with Hibernate many-to-many association
This post is really a record for both myself and anyone else who ever comes across the same problem.
The Problem: Given two entities with a many-to-many association between them, the join table isn’t being populated when an association is made.
The Problem Set: Two persistent entities, “Group” and “ActivityType” with a many-to-many association between them. A few snippets from the relevant files…
Group.hbm.xml
<set name="activityTypes" table="group_activity_type" cascade="save-update" lazy="true">
<key column="group_id"/>
<many-to-many column="activity_type_id" class="ActivityType"/>
</set>
ActivityType.hbm.xml
<set name="groups" table="group_activity_type" inverse="true" cascade="save-update" lazy="true">
<key column="activity_type_id"/>
<many-to-many column="group_id" class="Group"/>
</set>
Group.java
private Set activityTypes = new HashSet();
public Set getActivityTypes() {
return activityTypes;
}
public void setActivityTypes(Set activityTypes) {
this.activityTypes = activityTypes;
}
ActivityType.java
private Set groups = new HashSet();
public Set getGroups() {
return groups;
}
public void setGroups(Set groups) {
this.groups = groups;
}
Some test code
org.hibernate.classic.Session session = HibernateUtil.getSessionFactory().openSession();
session.setFlushMode(FlushMode.MANUAL);
ManagedSessionContext.bind(session);
session.beginTransaction();
Group group = new Group();
group.setName("Test Group");
ActivityType activityType = new ActivityType();
activityType.setName("Activity Type");
activityType.getGroups().add(group);
group.getActivityTypes().add(activityType);
activityTypeDAO.saveActivityType(activityType);
groupDAO.saveGroup(group);
ManagedSessionContext.unbind(HibernateUtil.getSessionFactory());
session.getTransaction().commit();
session.close();
The Solution: This took me ages to figure out but I eventually stumbled across the problem on this thread. The problem is that I’m not calling session.flush() before I commit the session. Here’s the last paragraph of test code with the new flush statement.
ManagedSessionContext.unbind(HibernateUtil.getSessionFactory());
session.flush();
session.getTransaction().commit();
session.close();