Hibernate session.contains(Class clazz,Serializable id)

时间:2011-09-19 15:59:01

标签: java hibernate session

我希望能够检查会话是否包含给定类/标识符的实体。我现在看不到这样做的方法。

  • contains()采用实体对象而非class + key
  • get()查询数据库是否存在我不想做的实体
  • load()永远不会返回null,因为始终会创建代理,因此我无法使用此方法

是否可以执行上述操作而没有对DB的副作用/查询?

6 个答案:

答案 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。