Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate会话。包含(类clazz,可序列化id)_Java_Hibernate_Session - Fatal编程技术网

Java Hibernate会话。包含(类clazz,可序列化id)

Java Hibernate会话。包含(类clazz,可序列化id),java,hibernate,session,Java,Hibernate,Session,我希望能够检查会话是否包含给定类/标识符的实体。我现在找不到这样做的方法 contains() get() load()永远不会返回null,因为始终会创建代理,因此我无法使用此方法 是否可以在没有副作用/对DB的查询的情况下执行上述操作?我不知道。如果您试图获取特定类型和id的实体,而该实体不包含该实体,则会话将始终检查数据库 事实上,这是该模型的优点之一。您不必关心JPA/Hibernate从何处获取对象、缓存(第一级或第二级)或数据库 如果内存中有实体,可以检查它是否已从会话中删除,但

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

  • contains()
  • get()
  • load()
    永远不会返回null,因为始终会创建代理,因此我无法使用此方法

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

我不知道。如果您试图获取特定类型和id的实体,而该实体不包含该实体,则会话将始终检查数据库

事实上,这是该模型的优点之一。您不必关心JPA/Hibernate从何处获取对象、缓存(第一级或第二级)或数据库


如果内存中有实体,可以检查它是否已从会话中删除,但不检查它是否在会话中

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

回答我自己的问题

我认为这在公共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,因此如果它在内部发生更改,将来可能无法工作。

这可以工作:

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

    return false;
}
public静态布尔sessionContains(会话会话、类aClass、可序列化id){
返回Hibernate.i初始化(session.load(aClass,id));
}
session#load()
不会转到数据库并始终返回对象。 若返回的值是代理,那个么会话不包含传递的id/类对。
否则会话已经有了这个对象。

只是好奇-为什么需要知道具有给定标识符的对象是否在会话中?难道你不能只执行
get(id)
并依赖这样一个事实,即如果对象已经在会话中,Hibernate将返回该实例,而不是重新查询它吗?在这个实例中,我试图让Hibernate与一些自定义缓存交互,但只在非常特定的实例中进行交互,大多数时候,我对点击DB的默认行为感到高兴,因此我想检查会话中是否存在对象,如果不从缓存加载它的话。关键是我不能干扰会话中已经存在的任何内容,因为可能有来自其他对象的多对一引用对它的引用。@MikeQ您对IdentityMap的工作方式完全正确,因此我的答案现在被删除。这不是我想要的。您错了。session#load and session#getReference始终创建代理,从不检查数据库。
public static boolean sessionContains(Session session, Class<?> aClass, Serializable id) {
    return Hibernate.isInitialized(session.load(aClass, id));
}