0

我正在尝试使用 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对象有一个对象列表,GroupGroup对象又具有其他对象的列表。

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

很公平,所以我groups在退出交易之前急切地加载。

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

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

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

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

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

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

4

1 回答 1

0

通过删除未初始化的休眠代理解决了这个问题。这仅删除集合,因为这是我的要求。随意建议编辑以使其他用户受益。

第一剪:

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

}
于 2013-05-06T08:51:22.057 回答