我可以在JAXWS Web服务方法中将Hibernate实体作为返回值返回吗?

时间:2011-04-18 08:47:09

标签: java web-services hibernate jpa jax-ws

任何人都可以告诉我,我可以在JAXWS Web服务方法中返回Hibernate Entities作为返回值吗?

确实我有一些这样的实体:

@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;
    }
}

当我从客户端调用此Web方法时,我得到LazyInitializationException异常:(

我测试Serializable和Cloneable接口并覆盖克隆方法,但不幸的是它不起作用,我在管理器中使用了em.detach(parent),但它仍然不能正常工作。

任何人都可以帮助我吗?

tnax

1 个答案:

答案 0 :(得分:7)

这是值得商榷的。通常,您有两种选择:

  • 返回实体,但请确保它们已初始化。使用@*ToMany标记fetch=FetchType.EAGER或使用Hibernate.initialize(..)。异常的原因是默认情况下,在请求之前,不会从数据库中提取实体中的所有集合。但是当你从jax-ws序列化程序请求它们时,hibernate会话已经关闭。从技术上讲,你可以有一些OpenSessionInViewIntercepetor,但我认为JAX-WS没有现成的东西,写一个可能是个问题。如果您不想传输这些集合,可以使用@XmlTransient(或@JsonIgnore注释它们,具体取决于序列化技术)。它使实体有点混乱,但我仍然更喜欢它来编码重复。

  • 使用DTO(数据传输对象) - 将所有数据从实体传输到具有类似结构的新对象,该对象将由Web服务公开。再次,您必须确保在休眠会话激活时填充DTO

我更喜欢第一个选项,因为它需要更少的biolerplate代码,但我同意在使用它时应该非常小心实体状态管理。