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();