我希望能够检查会话是否包含给定类/标识符的实体。我目前看不到这样做的方法。Hibernate session.contains(Class clazz,Serializable id)
- 需要一个实体对象不是类+键
get()
查询数据库,如果实体不存在,我不想做load()
作为代理总是会创建这样从不返回null我不能使用这种方法
是否有可能做到上述没有副作用/查询数据库?
我希望能够检查会话是否包含给定类/标识符的实体。我目前看不到这样做的方法。Hibernate session.contains(Class clazz,Serializable id)
get()
查询数据库,如果实体不存在,我不想做load()
作为代理总是会创建这样从不返回null我不能使用这种方法是否有可能做到上述没有副作用/查询数据库?
回答我自己的问题。
我不认为这是可能的公共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,所以如果它在内部的变化可能不会在将来的工作。
不是我所知道的。如果您尝试获取特定类型和ID的实体并且它不包含该实体,会话将始终检查数据库。
事实上,这是模型的好处之一。您不必关心JPA/Hibernate从哪里获取对象,高速缓存(第1级或第2级)还是数据库。
如果您在内存中有一个实体,您可以检查它是否与会话脱离,但如果它在会话中则不会。
这工作:
public boolean isIdLoaded(Serializable id)
{
for (Object key : getSession().getStatistics().getEntityKeys())
{
if (((EntityKey) key).getIdentifier().equals(id))
{
return true;
}
}
return false;
}
只是好奇 - 为什么你需要知道,如果给定标识的对象是在会话?难道你不能只是做'get(id)'并且依靠这样一个事实,即如果这个对象已经在Session中,那么Hibernate将返回那个实例而不是为它重新查询? –
在这个例子中,我试图让hibernate和一些自定义缓存进行交互,但是只有在非常特定的情况下,大部分时间我都很喜欢击中数据库的默认行为,所以我想检查会话是否存在一个对象如果不从缓存中加载它。关键是我不能干扰会话中已有的任何内容,因为可能会从其他对象引用多对一的引用。 –
@MikeQ您对IdentityMap的工作方式绝对正确,因此我的答案现在已被删除。 – Marcelo