2012-03-06 21 views
1

讓我們說我正在嘗試使用一個寧靜的界面列出所有產品。JAX-RS:我如何有選擇地在Restful調用中選擇xml輸出?

@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 

我不想包括產品的用戶在我休息的xml輸出。我如何有選擇地選擇包含在xml中的內容?

我正在使用REST-Easy,JBoss AS7,JPA和Hibernate作爲實現。我的EJB 3.1方法公開爲Restful服務。

感謝您的幫助!

回答

3

我不會建議在一個類中混合使用JAXB和JPA。

JPA實體有它自己的特殊生命週期。如果您從公共EJB方法返回JPA實體,則在大多數情況下它將被分離。我假設你的REST資源類是EJB。 JPA實體是分離的,因爲默認情況下,您的事務將以調用公共EJB方法開始和結束。有關更多信息,請參閱TransactionAttribute的JavaDoc。如果JPA實體被分離,則延遲加載將不再起作用。那是你的問題。

我建議爲JPA實體和JAXB實體分別設置類。此外,我會建議永遠不要從其事務上下文中返回一個JPA實體。所以你將永遠不必處理JPA實體的分離/合併。你所有的懶惰加載問題都是歷史。爲了實現這一點,您必須手動將JPA實體轉換爲事務內部的JAXB實體(在公共EJB方法中)並返回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實體你有什麼進入你的輸出,並沒有什麼完全控制。

+0

亞歷克斯,這種方法是有道理的。我會嘗試。但是,如果我的前端想要使用JPA實體(以使用驗證器),我最終將在我的EJB上創建兩個獨立的方法用於前端使用,另一個用於公開作爲Restful方法。是否有任何其他優雅的方式來選擇JPA實體的哪些集合在服務調用中公開? – 2012-03-07 00:49:00

+0

Alex,如果我分離上面的JpaProduct並調用product.setProductUsers(null),與您建議的內容(創建單獨的JaxbProduct)相比,您是否認爲有任何缺點? – 2012-03-07 01:12:40

+0

@Veer當你說'前端'時,你是什麼意思?你可以請你勾畫你的建築堆棧。 – 2012-03-09 09:17:16