2017-03-09 59 views
1

我有这个实体用户,它有一个角色集合(Set),我想重新缓存,所以无论何时调用getRoles(),它都会返回一个缓存副本。明确加载实体的集合

这里的结构至今:

  1. User.roles是为lazy = “true”,并访问= “场”。
  2. User.getRoles()具有一个侦听器,该侦听器调用spring @Cacheable方法 ,该方法从redis缓存而不是第二级缓存中检索。

映射信息:

<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> 

这里是GetRoles():

public Set getRoles() { 
     if(!rolesUpdated && this.id!=null){ 
      ApplicationContextProviderNonManageBean.getApplicationContext().publishEvent(
       new com.resolution.scheduler.dao.event.UserRoleGetEvent(this)); 
     } 
       return roles; 
    } 

这里的时候UserRoleGetEvent事件触发了所谓:

@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]; 
    } 

这里的UserRoleGetEvent是如何工作的:

public void onApplicationEvent(UserRoleGetEvent event) { 
     PersistentSet roles = userManager.getUserRoleByUserId(event.getUser().getId()); 
     event.getUser().setRoles((roles)); //**THIS_SET_MAKES_IT_DIRTY** 

    } 

问题: 当我做user.getRole(),因为它为user.roles设置了一个新的集合,并且会话变得很脏。 在这个肮脏的会话中,每当刷新被称为delete全部roles和它insert所有角色再次,即使没有实际变化。我在寻找的是如何让hibernate认为我的新集合像会话检索(实际上不是这样)并且不认为它是肮脏的。

任何解决方法或建议?

+0

类似的问题:http://stackoverflow.com/questions/34763402/proper-cache- spring-hibernate的用法 –

+0

@DraganBozanovic ummm ..不,它与你链接的不同,因为它与加载子关系有关。 –

回答

0

Hibernate不喜欢它的集合被改变。什么可能的工作是一样的东西:

event.getUser().getRoles().clear(); 
event.getUser().getRoles().addAll(roles); 

但后来,我有点被你正在尝试做的困惑。 User上的getRoles触发事件,然后更改角色?

作为一个方面说明,我被存储在这里工作,但你的代码可以重构这个:

@Cacheable(value="userRoleByUserId" , key="#userId", condition="#userId!=null") 
public List<Role> getUserRoleByUserId(final Long userId){ 
    if(userId==null){ 
     return Collections.emptyList(); 
    } 
    log.info("USer Role Getting from Database for User Id : "+userId); 

    @SuppressWarning("unchecked") 
    List<Role> result = (List<Role>) getHibernateTemplate().executeWithNativeSession(new HibernateCallback<Object>(){ 
     public Object doInHibernate(Session session) throws HibernateException{ 
      return session.createQuery("Select u.roles from User u where u.id=:userId").setParameter("userId",userId).list(); 
     } 
    }); 
    log.info(set); 

    return result; 
} 

public void onApplicationEvent(UserRoleGetEvent event) { 
    List<Role> roles = userManager.getUserRoleByUserId(event.getUser().getId()); 
    event.getUser().getRoles().clear(); // yes, I know, getRoles will throw an event and send you in an infinite loop... Fixing that just means having another method 
    event.getUser().getRoles().addAll(roles); 
} 
+0

getRoles()有一个触发事件,它调用getUserRoleByUserId()。再次调用getRoles()将是stackoverflow。 –

+0

是的。这就是为什么我说它会在行评论。只需使用'getRolesThatDontTriggerAnEvent'方法 – Henri

相关问题