1

假设我正在尝试使用宁静的界面列出所有产品。

    @XmlRootElement
    public class Product implements Serializable {

    //products attributes defined here

    @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="product")
    private Set<ProductUser> productUsers= new HashSet<ProductUser>();
}

当我尝试在产品上调用 find.All 时,它甚至试图获取 ProductUsers 并引发异常

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role, productUsers, no session or session was closed

我不想在我的 rest xml 输出中包含产品用户。如何有选择地选择 xml 中包含的内容?

我使用 REST-Easy、JBoss AS7、JPA 和 Hibernate 作为实现。我的 EJB 3.1 方法公开为 Restful 服务。

感谢你的帮助!

4

1 回答 1

3

我不建议将 JAXB 和 JPA 混合在一个类中。

JPA 实体有自己的特殊生命周期。如果从公共 EJB 方法返回 JPA 实体,则在大多数情况下它是分离的。我假设您的 REST 资源类是 EJB。JPA 实体是分离的,因为默认情况下,您的事务将以调用公共 EJB 方法开始和结束。有关更多信息,请查看TransactionAttribute的 JavaDoc 。如果 JPA 实体被分离,延迟加载将不再起作用。那是你的问题。

我建议为 JPA 实体和 JAXB 实体设置单独的类。此外,我建议永远不要将 JPA 实体从其事务上下文中返回。因此,您将永远不必处理 JPA 实体的分离/合并。您所有的延迟加载问题都将成为历史。为此,您必须在事务中(在公共 EJB 方法中)手动将 JPA 实体转换为 JAXB 实体并返回 JAXB 实体。

您的 GET 方法可能如下所示:

@GET
@Produces("application/xml")
public JaxbProduct get(@PathParam("id") int id) {
    JpaProduct product = entityManager.find(JpaProduct.class, id);
    JaxbProduct result = new JaxbProduct();
    result.setPropertyX(product.getPropertyX());
    return result;
}

通过手动将您的 JPA 实体转换为 JAXB 实体,您可以完全控制哪些内容进入您的输出,哪些没有。

于 2012-03-06T23:13:08.720 回答