【问题标题】:Cannot serialize JPA bean due to presence of proxies由于存在代理,无法序列化 JPA bean
【发布时间】:2013-05-04 17:01:52
【问题描述】:

我正在尝试使用 JAX-RS 将对象公开为 XML。

我有一个名为 Client 的类,我正在返回它的实例,如下所示:

    @Transactional(readOnly=true)
    @GET
    @Produces("application/xml")
    @Path("/{clientId}.xml")
    public Client getCleintAsXML(@PathParam("clientId") int clientId) {
        Client c = em.find(Client.class, clientId);
        return c;
    }

但是Client 对象有一个Group 对象的列表,而Group 对象又具有其他对象的列表。

当 JAX-RS 尝试序列化 Client 对象时,它会遍历整个对象图。当它遇到 groups 的 Hibernate 代理时,代码会中断,因为延迟加载仅在事务内部起作用。

很公平,所以我在退出事务之前急切地加载了groups

但它仍然失败,因为每个 Group 对象又具有一对多的关系,即更多的代理列表。

我什至不需要它们在输出中。我意识到如果删除这些代理,即设置为空,我的问题将得到解决。

我不想手动将它们设置为 null,因为这容易出错且不可维护。有没有办法自动做到这一点?

或者我可以告诉hibernate不要为这个特定的查询使用代理吗?还是只使用 1 级深度的代理?

我在 JPA 后面使用 Hibernate。我尽可能不希望直接引用 Hibernate。

我发现了十几个由不同用户编写的类来摆脱代理。有没有标准的方法来做到这一点?如果这是一个如此普遍的问题,我想会有一个标准的解决方案。

【问题讨论】:

  • Hibernate POJO 不可序列化。例如,GWT 有问题,请参阅此处developers.google.com/web-toolkit/articles/…您没有使用 GWT,但您的环境中是否有类似的问题?
  • 不,不是这样。 Hibernate 使用代理将数据的获取延迟到实际需要数据的时间。如果对象被分离,那将失败。我通过使用反射删除所有未初始化的 HibernateProxies 解决了这个问题。

标签: hibernate jpa jersey jax-rs


【解决方案1】:

通过删除未初始化的休眠代理解决了这个问题。这仅删除集合,因为这是我的要求。为了其他用户的利益,请随意提出修改建议。

初剪:

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;

import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.Hibernate;
import org.hibernate.collection.PersistentCollection;
import org.springframework.beans.BeanUtils;

public class HibernateProxyCleaner {

    public static Object clean(Object bean) {
        return clean(bean,0,2);
    }

    public static Object clean(Collection bean, int depth, int maxDepth) {
        if (bean == null || depth>maxDepth)
            return bean;

        for (Object o : (Collection) bean) {
            clean(o,depth,maxDepth);
        }

        return bean;
    }

    public static Object clean(Object bean, int depth, int maxDepth) {
        if (bean == null || depth>maxDepth)
            return bean;

        try {
            PropertyDescriptor[] pda = BeanUtils.getPropertyDescriptors(bean
                    .getClass());

            for (PropertyDescriptor pd : pda) {
                Object o = PropertyUtils.getProperty(bean, pd.getName());
                if (o != null) {
                    if (o instanceof PersistentCollection) {
                        if (PropertyUtils.isReadable(bean, pd.getName()) && PropertyUtils.isWriteable(bean, pd.getName())) {
                            if (!Hibernate.isInitialized((PersistentCollection) o)) {
                                o = null;
                                PropertyUtils.setProperty(bean, pd.getName(), o);
                            }

                        }
                    } else {
                        clean(o,depth+1,maxDepth);
                    }
                }


            }
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return bean;
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    • 2016-02-02
    • 2023-03-10
    • 1970-01-01
    • 2015-08-19
    • 1970-01-01
    • 2016-09-09
    相关资源
    最近更新 更多