如何取消代理休眠对象[重复]

Posted

技术标签:

【中文标题】如何取消代理休眠对象[重复]【英文标题】:how to unproxy a hibernate object [duplicate] 【发布时间】:2012-06-29 00:58:02 【问题描述】:

如何取消代理休眠对象以支持多态性?

考虑以下示例。 A 类和 B 类是两个休眠实体。 B有两个亚型C和D。

List<A> resultSet = executeSomeHibernateQuery();
for(A nextA : resultSet) 
    for(B nextB : nextA.getBAssociations() 
        if(nextB instanceof C) 
            // do something for C
         else if (nextB instanceof D) 
            // do something for D
        
    

此代码无法执行 C 或 D 块,因为 B 集合已被延迟加载,并且 B 的所有实例都是 Hibernate 代理。我想要一种取消代理每个实例的方法。

注意:我意识到可以优化查询以急切地获取所有 B。我正在寻找替代方案。

【问题讨论】:

我知道这是一个老问题,但由于它作为谷歌搜索的第一个结果出现,我必须在这里评论,如果你必须使用instanceof,那么你可能正在做多态性错误。 【参考方案1】:

这是我们的解决方案,已添加到我们的持久化工具中:

public T unproxy(T proxied)

    T entity = proxied;
    if (entity instanceof HibernateProxy) 
        Hibernate.initialize(entity);
        entity = (T) ((HibernateProxy) entity)
                  .getHibernateLazyInitializer()
                  .getImplementation();
    
    return entity;

【讨论】:

此解决方案是否适合您?我已经实现了类似的方法,我仍然有一个HibernateProxy 作为我的对象的一个​​类。这是我的问题:***.com/q/11518091/845220 这并没有解决PersistentCollection 的问题。通常,您可能拥有一个实际上已被代理为PersistentCollectionList&lt;Entity&gt;。如果通过此方法,测试entity instanceof HibernateProxy 将失败并且该方法将返回而不做任何事情。一个解决方案是同时测试entity instanceof PersistentCollection,同时使用Hibernate.initialize(),然后迭代并取消代理集合的每个对象。描述起来比实现更容易...... 请注意,您不需要检查实体是否不为空(请参阅***.com/questions/2950319/…)【参考方案2】:

现在 Hibernate 有专门的方法:org.hibernate.Hibernate#unproxy(java.lang.Object)

【讨论】:

YourEntity unproxiedEntity = (YourEntity) Hibernate.unproxy(yourEntity);【参考方案3】:

使用HibernateProxy和getImplementationMethod的解决方案是正确的。

但是,我假设您遇到了这个问题,因为您的集合被定义为一个接口,并且 hibernate 正在向该接口提供代理。

这导致了设计问题,为什么要使用“if”和“instanceof”而不是使用接口方法来做你需要的事情。

所以你的循环变成了:

for(B nextB : nextA.getBAssociations() 
    nextB.doSomething();

这样,hibernate 会将对“doSomething()”的调用委托给实际的实现对象,而您永远不会知道其中的区别。

【讨论】:

好点,我们对继承的使用可能不太理想。在这种特殊情况下,我们实际上还有其他逻辑,具体取决于集合中每个项目的类型。所以我们可以做的一件事是添加 isC() 和 isD() 抽象方法,但这也有点笨拙。 FWIW,我们的层次结构适用于我们的大多数用例,这是 20% 的一部分。

以上是关于如何取消代理休眠对象[重复]的主要内容,如果未能解决你的问题,请参考以下文章

休眠:具有相同标识符值的不同对象已与会话相关联[重复]

对象引用未保存的瞬态实例 - 在刷新休眠 JPA 之前保存瞬态实例 [重复]

休眠强制时间戳以 UTC 形式持续/加载 [重复]

如何在休眠中重复嵌入类型

我正在尝试创建一个简单的休眠应用程序。它给出了以下错误。如何解决该错误[重复]

取消设置循环内对象的当前属性[重复]