8

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

考虑以下示例。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。我正在寻找替代方案。

4

3 回答 3

19

这是我们的解决方案,添加到我们的持久性实用程序中:

public T unproxy(T proxied)
{
    T entity = proxied;
    if (entity instanceof HibernateProxy) {
        Hibernate.initialize(entity);
        entity = (T) ((HibernateProxy) entity)
                  .getHibernateLazyInitializer()
                  .getImplementation();
    }
    return entity;
}
于 2012-06-27T14:46:04.693 回答
14

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

于 2019-03-07T13:27:59.100 回答
2

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

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

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

所以你的循环变成:

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

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

于 2012-06-27T19:08:57.663 回答