我创建了一个公开为Web服务(REST)的EJB。但是,当我尝试它时,我得到以下例外。我将其追溯到我在问题实体上的JPA注释。当我取消注释@ManyToOne
映射(具有fetch属性的映射)时,它似乎抛出此异常。我故意将实体可能与其他实体建立的所有关系都FetchType.LAZY
。我想保持这种方式。
我正在使用容器管理的事务和所有正常的EJB荣耀。为什么会这样?有什么修复?
修改
我有一个用@Stateless
注释的存储库类,然后我在另一个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) at sun.reflect.GeneratedMethodAccessor76.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect.Method.invoke(Method.java:601)at 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)at 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 .__调用(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)at 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)|#]
答案 0 :(得分:2)
我遇到了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方法时,将加载并显示您的答案,问题和反馈。
答案 1 :(得分:0)
LazyInitializationException
:在Session
(否则:EntityManager
)关闭后,其实体将分离。问题是,对象(QuestionFeedback
,QuestionCategory
和Answer
)的集合是分离的。如果您在lazy=false
中使用FetchType.EAGER
(否则:hibernate
),即使Session
已关闭,对象集合也会加载到内存中。