2011-09-19 31 views
6

我希望能够检查会话是否包含给定类/标识符的实体。我目前看不到这样做的方法。Hibernate session.contains(Class clazz,Serializable id)

  • 需要一个实体对象不是类+键
  • get()查询数据库,如果实体不存在,我不想做
  • load()作为代理总是会创建这样从不返回null我不能使用这种方法

是否有可能做到上述没有副作用/查询数据库?

+0

只是好奇 - 为什么你需要知道,如果给定标识的对象是在会话?难道你不能只是做'get(id)'并且依靠这样一个事实,即如果这个对象已经在Session中,那么Hibernate将返回那个实例而不是为它重新查询? –

+0

在这个例子中,我试图让hibernate和一些自定义缓存进行交互,但是只有在非常特定的情况下,大部分时间我都很喜欢击中数据库的默认行为,所以我想检查会话是否存在一个对象如果不从缓存中加载它。关键是我不能干扰会话中已有的任何内容,因为可能会从其他对象引用多对一的引用。 –

+0

@MikeQ您对IdentityMap的工作方式绝对正确,因此我的答案现在已被删除。 – Marcelo

回答

1

回答我自己的问题。

我不认为这是可能的公共API。但是,如果你愿意忍受一些奶酪,你可以做以下

 SessionImplementor sessionImplementor = ((SessionImplementor)session); 
     EntityPersister entityPersister = sessionImplementor.getFactory().getEntityPersister(clazz.getName()); 
     PersistenceContext persistenceContext = sessionImplementor.getPersistenceContext(); 

     EntityKey entityKey = new EntityKey(id, entityPersister, EntityMode.POJO); 

     Object entity = persistenceContext.getEntity(entityKey); 

     if (entity != null) 
      return entity; 

     entity = persistenceContext.getProxy(entityKey); 

     if (entity != null) 
      return entity; 

     return null; 

这依赖于休眠的内部API,所以如果它在内部的变化可能不会在将来的工作。

1

不是我所知道的。如果您尝试获取特定类型和ID的实体并且它不包含该实体,会话将始终检查数据库。

事实上,这是模型的好处之一。您不必关心JPA/Hibernate从哪里获取对象,高速缓存(第1级或第2级)还是数据库。

如果您在内存中有一个实体,您可以检查它是否与会话脱离,但如果它在会话中则不会。

0

使用getIdentifier(..)。它返回与当前会话关联的给定实体的标识符值,参见Javadoc

+0

这不是我要求的。 –

3

这工作:

public boolean isIdLoaded(Serializable id) 
{ 
    for (Object key : getSession().getStatistics().getEntityKeys()) 
    { 
     if (((EntityKey) key).getIdentifier().equals(id)) 
     { 
      return true; 
     } 
    } 

    return false; 
}