Могу ли я возвращать объекты Hibernate в качестве возвращаемого значения в методах веб-службы JAXWS?

#java #web-services #hibernate #jpa #jax-ws

#java #веб-службы #переход в спящий режим #jpa #jax-ws

Вопрос:

Может ли кто-нибудь сказать мне, могу ли я возвращать объекты Hibernate в качестве возвращаемого значения в методах веб-службы JAXWS!?

Действительно, у меня есть некоторые объекты, подобные этим:

 @Entity
public class Parent {
...
    private Childone childoneByChildoneid;    
    @ManyToOne
    public
    @javax.persistence.JoinColumn(name="ChildOneId",referencedColumnName="Id")
    Childone getChildoneByChildoneid() {
        return childoneByChildoneid;
    }    
    public void setChildoneByChildoneid(Childone childoneByChildoneid) {
        this.childoneByChildoneid = childoneByChildoneid;
    }
...
}

@Entity
public class Childone {
...
    private Collection<Parent> parentsById;
    @OneToMany(mappedBy = "childoneByChildoneid")
    public Collection<Parent> getParentsById() {
        return parentsById;
    }
    public void setParentsById(Collection<Parent> parentsById) {
        this.parentsById = parentsById;
    }
...
}
  

И у вас есть такая служба:

 @Stateless
@WebService()
public class MasterDataService {
    @EJB
    private MasterDataManager manager;
    @WebMethod
    public Parent getParent(int parentId) {
        return manager.getParent(parentId);
    }
}
@Stateless
public class MasterDataManager {
    @PersistenceContext
    EntityManager em;

    public Parent getParent(int parentId) {
        Parent parent = (Parent) em.createQuery(
            "select p from Parent p where p.id=:parentId")
            .setParameter("parentId", parentId).getSingleResult();
        return parent;
    }
}
  

Когда я вызываю этот веб-метод из клиента, я получаю исключение LazyInitializationException : (

Я тестирую сериализуемые и клонируемые интерфейсы и переопределяю метод clone, но, к сожалению, он не работает, я использую em.detach (родительский) в диспетчере, но он все еще не работает.

Кто-нибудь может мне помочь?

tnax

Ответ №1:

Это спорно. Как правило, у вас есть два варианта:

  • верните объекты, но убедитесь, что они инициализированы. Либо отметьте @*ToMany с помощью fetch=FetchType.EAGER , либо используйте Hibernate.initialize(..) . Причина исключения заключается в том, что по умолчанию все коллекции в entities не извлекаются из базы данных до запроса. Но когда вы запрашиваете их у сериализатора jax-ws, сеанс гибернации уже закрыт. Технически, у вас может быть несколько OpenSessionInViewIntercepetor , но я не думаю, что есть что-то готовое к использованию с JAX-WS, и может возникнуть проблема с его написанием. Если вы не хотите передавать эти коллекции, вы можете пометить их с помощью @XmlTransient (или @JsonIgnore , в зависимости от метода сериализации). Это приводит к некоторому беспорядку в сущности, но я все еще предпочитаю это дублированию кода.

  • Используйте DTO (объекты передачи данных) — перенесите все данные из объекта в новый объект с аналогичной структурой, который будет предоставлен веб-службой. Опять же, вам нужно убедиться, что вы заполняете DTO, когда активен сеанс гибернации

Я предпочитаю первый вариант, потому что он требует меньше кода biolerplate, но я согласен, что при его использовании следует быть очень осторожным с управлением состоянием объектов.

Комментарии:

1. привет, дорогой Божо 🙂 Мне нравится, что вы предпочитаете первый вариант, но есть большая проблема. Возможно, у нас есть большой объект со многими отношениями, и нам не хотелось бы возвращать все эти отношения целиком. Другими словами, возможно, мы вернем этот большой объект с некоторыми отношениями в одном сценарии и вернемся с другими отношениями в другом сценарии. Есть ли решение этой проблемы? Спасибо за ваше внимание.