I have this entity User and it has a roles collection(Set) which I want to redis cache so whenever it's calling getRoles(), it return a cached copy.
Here's the structure so far:
- User.roles is lazy="true" and access="field".
- User.getRoles() has a listener that calls a spring @Cacheable method which retrieves from redis cache rather than 2nd level cache.
Mapping information:
<set
name="roles"
table="user_role"
lazy="true"
cascade="none"
access="field"
>
<key
column="user_id"
>
</key>
<many-to-many
class="com.resolution.scheduler.model.Role"
column="role_id"
outer-join="auto"
/>
</set>
Here is GetRoles():
public Set getRoles() {
if(!rolesUpdated && this.id!=null){
ApplicationContextProviderNonManageBean.getApplicationContext().publishEvent(
new com.resolution.scheduler.dao.event.UserRoleGetEvent(this));
}
return roles;
}
Here's what's called when UserRoleGetEvent event fires:
@Cacheable(value="userRoleByUserId" , key="#userId", condition="#userId!=null")
public PersistentSet getUserRoleByUserId(final Long userId){
if(userId==null){
return new PersistentSet();
}
log.info("USer Role Getting from Database for User Id : "+userId);
//final List<Role> roles=(List<Role>)getHibernateTemplate().find("Select u.roles from User u where u.id=?",userId);
final PersistentSet[] set= new PersistentSet[1];
getHibernateTemplate().executeWithNativeSession(new HibernateCallback<Object>(){
public Object doInHibernate(Session session) throws HibernateException{
List roles=session.createQuery("Select u.roles from User u where u.id=:userId").setParameter("userId",userId).list();
set[0]= new PersistentSet((SessionImpl)session, new HashSet(roles));
return null;
}
});
log.info(set);
return set[0];
}
Here's how UserRoleGetEvent works:
public void onApplicationEvent(UserRoleGetEvent event) {
PersistentSet roles = userManager.getUserRoleByUserId(event.getUser().getId());
event.getUser().setRoles((roles)); //**THIS_SET_MAKES_IT_DIRTY**
}
Problem:
When I do user.getRole()
, as it set a new collection to user.roles and it makes session dirty. On this dirty session, whenever flush is called it delete
all roles
and it insert
all roles again even when there was no actual change. What I'm looking for is how can I make hibernate to think my new collection is like session retrieved(which is not actually) and don't consider it as dirty.
Any workarounds or suggestion?