Hi,
I have a problem when deleting from a many-to-many associations in our object model when filters are on. I believe it is due to a faulty optimization or because filters are not applied when writing.
Here is the case:
I have 2 entities: Group and Role. Group has a many-to-many relationship with Role and Role has an attribute called domain.
On the Group mapping document, we have a filter set up on the <many-to-many> association to Role that discriminate based on its domain attribute:
Code:
<set name="assignedRoles" table="security_group_to_role" lazy="true" cascade="save-update" access="property">
<key column="group_id"/>
<many-to-many class="SecurityRoleImpl" column="role_id">
<filter name="FilterSecurityObjectBasedOnDomainId" condition="domain=:domain"/>
</many-to-many>
</set>
Here the sequence of events that causes my problem when trying to reassociate different roles to the Group:
I load a Group Object
I call Hibernate.initialize(group.getRoles()) to activate the collection
I remove all roles in the collection by calling the Collection.remove() method for each role.
I persist the Group.
The SQL that gets executed is: delete from security_group_to_role where groupId = ?
This makes no sense since there are other roles associated through this table, but they were just not loaded at first (and hence not deleted) because the filter was up.
If I do not delete all roles in the collection, hibernate executes many statement like: delete from security_group_to_role where groupId=? and roleId=?
Is this a bug? If no, what is the workaround?
Hibernate version: 3.0.3
The unit test:
Code:
public void testResettingRolesForGroupUnderADomainIdDoesNotImpactAssociationsUnderAnotherDomainId() {
service.setSecurityDomain(service.findSecurityDomainById(new Long(654456)));
SecurityGroup group = service.findSecurityGroupById(new Long(512454));
Collection roles = service.getAssociatedRolesForGroup(group);
assertTrue("Could not retrieve associated roles for a group when filtered by domain", roles.size() > 0);
service.associateRolesToGroup(group, new ArrayList());// assigning nothing...
roles = service.getAssociatedRolesForGroup(group);
assertEquals("There should be no more roles associated to this group",0, roles.size());
service.setSecurityDomain(service.findSecurityDomainById(new Long(654457)));
group = service.findSecurityGroupById(new Long(512454));
roles = service.getAssociatedRolesForGroup(group);
assertEquals("Roles for another domain were deleted...", 1, roles.size());
}
Thanks in advance for your help :)