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