JAX-RS: Как мне выборочно выбрать вывод xml в вызове Restful? - PullRequest
1 голос
/ 07 марта 2012

Допустим, я пытаюсь составить список всех продуктов, используя удобный интерфейс.

    @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.

Ценю вашу помощь!

1 Ответ

3 голосов
/ 07 марта 2012

Я бы не советовал смешивать JAXB и JPA в одном классе.

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

...