我希望能够检查会话是否包含给定类/标识符的实体。我现在看不到这样做的方法。
contains()
采用实体对象而非class + key get()
查询数据库是否存在我不想做的实体load()
永远不会返回null,因为始终会创建代理,因此我无法使用此方法是否可以执行上述操作而没有对DB的副作用/查询?
答案 0 :(得分:4)
这有效:
public boolean isIdLoaded(Serializable id)
{
for (Object key : getSession().getStatistics().getEntityKeys())
{
if (((EntityKey) key).getIdentifier().equals(id))
{
return true;
}
}
return false;
}
答案 1 :(得分:1)
不是我知道的。如果您尝试获取特定类型和ID的实体并且它不包含它,则会话将始终检查数据库。
事实上,这是该模型的好处之一。您不必关心JPA / Hibernate从哪里获取对象,缓存(第一级或第二级)或DB。
如果您在内存中有实体,则可以检查它是否从会话中删除,但如果它在会话中则不会。
答案 2 :(得分: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;
这依赖于hibernate的内部API,因此如果它在内部发生变化,将来可能无法正常工作。
答案 3 :(得分:0)
使用getIdentifier(..)
。它返回与当前会话关联的给定实体的标识符值,请参阅Javadoc。
答案 4 :(得分:0)
public static boolean sessionContains(Session session, Class<?> aClass, Serializable id) {
return Hibernate.isInitialized(session.load(aClass, id));
}
session#load()
不会转到数据库,而是始终返回Object。
如果返回值是代理,则会话不包含传递的ID /类对。
否则,会话已经具有该对象。
答案 5 :(得分:0)
$L$106:$L$110
如果实体在会话缓存中,则 getReference() 返回实体,否则返回代理对象。如果对象是代理,则 isLoaded() 返回 false。