2012-03-06 1 views
1

Скажем, я пытаюсь перечислить все продукты, используя приятный интерфейс.JAX-RS: Как выбрать выборочный вывод xml в режиме «Restful call»?

@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 Entities есть есть собственный специальный жизненный цикл. Если вы возвращаете объект JPA из общедоступного метода EJB, он в большинстве случаев отключается. Я предполагаю, что ваши классы ресурсов REST являются EJB. Объект JPA отключен, поскольку по умолчанию транзакция начнется и завершится вызовом общедоступного метода EJB. Для получения дополнительной информации смотрите JavaDoc для TransactionAttribute. Если объект 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

Alex, Этот метод имеет смысл. Я попробую. Но если мой фронт хочет использовать сущности JPA (чтобы использовать валидаторы), я создам два отдельных метода для своих EJB для использования на передней панели, а другой для разоблачения как методы Restful. Есть ли другой элегантный способ выбора, какие коллекции JPA Entity становятся доступными в вызове службы? –

+0

Alex, Если я отсоединил JpaProduct выше и позвонил product.setProductUsers (null), вы думаете, что есть какие-то недостатки, по сравнению с тем, что вы предложили (создание отдельного JaxbProduct)? –

+0

@Veer Что вы имеете в виду, когда говорите «передний конец»? Можете ли вы набросать свой архитектурный стек. –