由于存在代理,无法序列化JPA bean

时间:2013-05-04 17:01:52

标签: hibernate jpa jersey jax-rs

我正在尝试使用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,我的问题就会得到解决。

我不想手动将它们设置为null,因为这容易出错且无法维护。有没有办法自动执行此操作?

或者,我可以告诉hibernate不使用此特定查询的代理吗?或者只使用1级深度的代理?

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

我找到了不同用户编写的十几个类来摆脱代理。有没有标准的方法来做到这一点?如果这是一个常见的问题,我猜,会有一个标准的解决方案。

1 个答案:

答案 0 :(得分:0)

通过删除未初始化的hibernate代理解决了这个问题。这只删除了我的要求。随意为其他用户提供修改建议。

首先剪切:

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;
    }

}