我创建了一个作为Web服务(REST)公开的EJB。但是,当我尝试时,我在下面遇到了异常。我将其追溯到我在Question实体上的JPA批注。当我取消注释@ManyToOne映射(带有fetch属性的映射)时,似乎引发了此异常。我故意将实体与其他实体之间可能具有的所有关系都设为FetchType.LAZY。我想保持这种方式。

我正在使用容器管理的事务和所有正常的EJB荣耀。为什么会这样?修复了什么?

编辑:
我有一个用@Stateless注释的存储库类,然后在另一个EJB中使用该类,该EJB从存储库中检索问题列表。最后,我有了一个资源,该资源也用@Stateless注释。是因为某些持久性上下文还是其他原因?

PS:我从实体中遗漏了所有其他内容,当我按照说明修复注释时,代码就起作用了。

@Entity
public class Question extends AbstractModel {

    private int id;
    private Participant participant;
    private List<Answer> answers;
    private List<QuestionCategory> categories;
    private List<QuestionFeedback> feedback;

    public Question() {
        answers = new ArrayList<Answer>();
        categories = new ArrayList<QuestionCategory>();
        feedback = new ArrayList<QuestionFeedback>();
    }

    @ManyToOne
    //@ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ParticipantId")
    public Participant getParticipant() {
        return participant;
    }

    //@OneToMany(cascade = CascadeType.ALL)
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "QuestionId", nullable = false)
    public List<Answer> getAnswers() {
        return answers;
    }

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "QuestionQuestionCategory",
            joinColumns = @JoinColumn(name = "QuestionId", nullable = false),
            inverseJoinColumns = @JoinColumn(name = "QuestionCategoryId", nullable = false)
    )
    public List<QuestionCategory> getCategories() {
        return categories;
    }

    //@OneToMany(cascade = CascadeType.ALL)
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "QuestionId", nullable = false)
    public List<QuestionFeedback> getFeedback() {
        return feedback;
    }
}


引发此异常:


  [#| 2012-11-11T00:10:59.182 + 0100 |警告| glassfish3.1.2 | javax.enterprise.system.container.web.com.sun.enterprise.web | _ThreadID = 71; _ThreadName = Thread-8; | StandardWrapperValve [javax.ws.rs.core.Application]:
  PWC1406:Servlet javax.ws.rs.core.Application的Servlet.service()
  抛出异常org.hibernate.LazyInitializationException:无法
  初始化代理-没有会话
  org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
    在
  org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:272)
    在
  org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
    在sun.reflect.GeneratedMethodAccessor76.invoke(未知源)处
  sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    在java.lang.reflect.Method.invoke(Method.java:601)在
  com.sun.xml.bind.v2.runtime.reflect.Accessor $ GetterSetterReflection.get(Accessor.java:354)
    在
  com.sun.xml.bind.v2.runtime.reflect.Accessor.getUnadapted(Accessor.java:147)
    在
  com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor $ CompositeTransducedAccessorImpl.hasValue(TransducedAccessor.java:251)
    在
  com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:105)
    在
  com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:358)
    在
  com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:350)
    在
  com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
    在
  com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:158)
    在
  com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:358)
    在
  com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
    在
  com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:69)
    在
  com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:172)
    在
  com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:159)
    在
  com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:358)
    在
  com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:593)
    在
  com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:340)
    在
  com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494)
    在
  com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323)
    在
  com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:178)
    在
  com.sun.jersey.json.impl.BaseJSONMarshaller.marshallToJSON(BaseJSONMarshaller.java:103)
    在
  com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.writeTo(JSONRootElementProvider.java:143)
    在
  com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:157)
    在
  com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306)
    在
  com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1437)
    在
  com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349)
    在
  com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339)
    在
  com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
    在
  com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
    在
  com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:708)
    在javax.servlet.http.HttpServlet.service(HttpServlet.java:770)处
  org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
    在
  org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    在
  org.apache.catalina.core.StandardContextValve._invoke(StandardContextValve.java:175)
    在
  org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java)
    在
  org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    在
  org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    在
  org.apache.catalina.core.StandardHostValve .__ invoke(StandardHostValve.java:161)
    在
  org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java)
    在
  org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    在
  org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    在
  com.sun.enterprise.v3.services.impl.ContainerMapper $ AdapterCallable.call(ContainerMapper.java:317)
    在
  com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    在
  com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
    在
  com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
    在
  com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
    在
  com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
    在
  com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    在
  com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    在
  com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    在
  com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    在
  com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    在
  com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    在com.sun.grizzly.ContextTask.run(ContextTask.java:71)处
  com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork(AbstractThreadPool.java:532)
    在
  com.sun.grizzly.util.AbstractThreadPool $ Worker.run(AbstractThreadPool.java:513)
    在java.lang.Thread.run(Thread.java:722)|#]

最佳答案

我遇到了Andy的确切问题。我到目前为止发现的是:

@ManyToOne
//@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ParticipantId")
public Participant getParticipant() {
    return participant;
}


您可以将LAZY设置为单个属性关联,但不应这样做。保留@ManyToOne批注:


  延迟属性获取:属性或单值关联为
  访问实例变量时获取。这种方法需要
  构建时字节码检测,很少需要。


至于Collections我已经添加了Hibernate.initialize(categories)像这样:


  有时需要在关闭前初始化代理或集合
  会议。您可以通过调用cat.getSex()强制初始化或
  例如cat.getKittens()。size()。但是,这可能会造成混淆
  对代码的读者来说,对于通用代码来说并不方便。的
  静态方法Hibernate.initialize()和Hibernate.isInitialized(),
  为应用程序提供了一种懒惰的便捷工作方式
  初始化的集合或代理。 Hibernate.initialize(cat)将
  强制初始化代理cat,只要其Session为
  还开着。 Hibernate.initialize(cat.getKittens())具有类似的功能
  收集小猫的效果。


@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "QuestionQuestionCategory",
        joinColumns = @JoinColumn(name = "QuestionId", nullable = false),
        inverseJoinColumns = @JoinColumn(name = "QuestionCategoryId", nullable = false)
)
public List<QuestionCategory> getCategories() {
    Hibernate.initialize(categories)
    return categories;
}


现在,我有一个org.hibernate.HibernateException: collection is not associated with any session异常。根据粗体显示,会议应为公开会议。我仍然找不到在容器管理的应用中启动会话的方法。仅仅调用getCategories()并不能达到代理或会话初始化的目的。

有小费吗?

编辑:解决方案

可能您想在用户单击某项然后触发action或actionListener时加载关联的集合。

您需要做的是(并且请非常通用):


find(Object id)方法实现Hibernate.initialize()方法(从上面的片段中的getCategories()方法中删除它):

public Question find(Object id) {
    Question question = getEntityManager().find(Question.class, id);
    Hibernate.initialize(question.getCategories());
    Hibernate.initialize(question.getAnswers());
    Hibernate.initialize(question.getFeedback());

    return question ;
}

当视图请求加载时搜索实体:

public void userHasClickedAQuestion(Object id) {
    selectedQuestion = questionFacade.find(id);
}



您完成了。调用getter方法时,将加载并显示您的答案,问题和反馈。

09-11 18:00