Hi all,
I've got the following test code:
Code:
@Test(groups = { "integration" })
public void testDeleteRoleWithGroups() throws Exception {
Group group = new Group(NULL_ID, GROUP_NAME);
Long groupPk = groupDao.saveOrUpdate(group);
Role role = new Role(NULL_ID, ROLE_NAME);
role.addGroup(group);
// It also adds a record to the MTM relationship table
Long rolePk = roleDao.saveOrUpdate(role);
// The group should have associated roles
Group actualGroup = groupDao.findByPk(Group.class, groupPk);
Assert.assertNotNull(actualGroup, "The actual group is empty");
Assert.assertFalse(actualGroup.getRoles().isEmpty(),
"The Set of roles from the group is empty");
// This will delete also the record from the MTM relationship table
roleDao.delete(role);
// This should be empty now
Role actualRole = roleDao.findByPk(Role.class, rolePk);
Assert.assertNull(actualRole,
"The actual role after deletion is not null!");
// We don't expect to find any roles in the roles relationship
Group emptyGroup = groupDao.findByPk(Group.class, groupPk);
Assert.assertNotNull(emptyGroup, "The group for PK: " + groupPk
+ " is null!");
Assert.assertTrue(emptyGroup.getRoles().isEmpty(),
"The set of roles for group with pk: " + groupPk
+ " is not empty!");
}
There is a MTM relationship between GROUPS and ROLES, with a MTM relationship table called ROLE_GROUP. The test fails for the last Assertion. This is what the test does:
1) Creates a Group and persists it
2) Creates a Role
3) Adds the Group to the Role
4) Persists the Role. At this point the MTM table is also updated (see SQL list below)
5) It retrieves the Group with the PK and it ensures that the Set of roles is not empty (more could have been done testing equality)
6) It deletes the Role. This also removes the record from the MTM table (see SQL list below)
7) It retrieves the Group again with the PK (the findByPk method uses Session.get(), which I knew it would always go to the database)
8) It ensures that the retrieved Group does not contain the Role which has been previously removed.
At point 8) is where I get the surprise. I knew that Session.get would always go to the database ,whereas it was Session.load which would search for the entity in the peristence context first. However I can't see the last SQL being generated and a result the Group.roles Set is still set with one entry.
However...
If I modify the code above by adding a getCurrentSession.clear() after the deletion of the Role I can see the last SQL being generated and the Set of Role is indeed empty. Is this the way it's supposed to work?
Below is the list of SQLs generated for the test above:
Hibernate:
/* insert uk.co.jemos.persistence.user.domain.Group
*/ insert
into
`
GROUP` (
GROUP_NAME, VERSION_NBR
)
values
(?, ?)
DEBUG 20 May - 23:13:24,862 hibernate.type.NullableType - binding 'groupName' to parameter: 1
DEBUG 20 May - 23:13:24,863 hibernate.type.NullableType - binding '0' to parameter: 2
Hibernate:
/* insert uk.co.jemos.persistence.user.domain.Role
*/ insert
into
`
ROLE` (
ROLE_NAME, VERSION_NBR
)
values
(?, ?)
DEBUG 20 May - 23:13:24,870 hibernate.type.NullableType - binding 'roleName' to parameter: 1
DEBUG 20 May - 23:13:24,870 hibernate.type.NullableType - binding '0' to parameter: 2
Hibernate:
/* update
uk.co.jemos.persistence.user.domain.Group */ update
`
GROUP` set
VERSION_NBR=?
where
GROUP_ID=?
and VERSION_NBR=?
DEBUG 20 May - 23:13:24,874 hibernate.type.NullableType - binding '1' to parameter: 1
DEBUG 20 May - 23:13:24,875 hibernate.type.NullableType - binding '90' to parameter: 2
DEBUG 20 May - 23:13:24,875 hibernate.type.NullableType - binding '0' to parameter: 3
Hibernate:
/* insert collection
row uk.co.jemos.persistence.user.domain.Role.groups */ insert
into
ROLE_GROUP
(ROLE_ID, GROUP_ID)
values
(?, ?)
DEBUG 20 May - 23:13:24,876 hibernate.type.NullableType - binding '27' to parameter: 1
DEBUG 20 May - 23:13:24,877 hibernate.type.NullableType - binding '90' to parameter: 2
Hibernate:
/* delete collection uk.co.jemos.persistence.user.domain.Role.groups */ delete
from
ROLE_GROUP
where
ROLE_ID=?
DEBUG 20 May - 23:13:24,881 hibernate.type.NullableType - binding '27' to parameter: 1
Hibernate:
/* delete uk.co.jemos.persistence.user.domain.Role */ delete
from
`ROLE`
where
ROLE_ID=?
and VERSION_NBR=?
DEBUG 20 May - 23:13:24,882 hibernate.type.NullableType - binding '27' to parameter: 1
DEBUG 20 May - 23:13:24,883 hibernate.type.NullableType - binding '0' to parameter: 2
Hibernate:
/* load uk.co.jemos.persistence.user.domain.Role */ select
role0_.ROLE_ID as ROLE1_1_0_,
role0_.ROLE_NAME as ROLE2_1_0_,
role0_.VERSION_NBR as VERSION3_1_0_
from
`ROLE` role0_
where
role0_.ROLE_ID=?
DEBUG 20 May - 23:13:24,885 hibernate.type.NullableType - binding '27' to parameter: 1
INFO 20 May - 23:13:24,966 context.transaction.TransactionalTestExecutionListener - Rolled back transaction after test execution for test context [[TestContext@4ef18d37 testClass = RoleEntityIntegrationTest, locations = array<String>['classpath:domain-user-spring-test-app.xml'], testInstance = uk.co.jemos.persistence.user.domain.test.integration.RoleEntityIntegrationTest@233d28e3, testMethod = testDeleteRoleWithGroups@RoleEntityIntegrationTest, testException = java.lang.reflect.InvocationTargetException]]
FAILED: testDeleteRoleWithGroups
java.lang.AssertionError: The set of roles for group with pk: 90 is not empty! expected:<true> but was:<false>