0

Web サービス (REST) として公開される EJB を作成しました。ただし、試してみると、以下の例外が発生します。Question エンティティの JPA アノテーションまでたどり着きました。@ManyToOneマッピング(フェッチ属性を持つもの)のコメントを外すと、この例外がスローされるようです。私は意図的に、エンティティが他のエンティティと持つ可能性のあるすべての関係を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: サーブレット 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.javasist.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) at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:358) at 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.com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:358) の serializeBody(SingleElementNodeProperty.java:158) 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) at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:157) at com.sun.jersey.spi.container com.sun.jersey.server.impl.application.WebApplicationImpl の .ContainerResponse.write(ContainerResponse.java:306)。bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323) at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:178) at com.sun.jersey.json.impl. com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.writeTo(JSONRootElementProvider.java:143) の BaseJSONMarshaller.marshallToJSON(BaseJSONMarshaller.java:103) com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider. writeTo(AbstractRootElementProvider.java:157) at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306) at com.sun.jersey.server.impl.application.WebApplicationImpl.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323) at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:178) at com.sun.jersey.json.impl. com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.writeTo(JSONRootElementProvider.java:143) の BaseJSONMarshaller.marshallToJSON(BaseJSONMarshaller.java:103) com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider. writeTo(AbstractRootElementProvider.java:157) at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306) at com.sun.jersey.server.impl.application.WebApplicationImpl.marshallToJSON(BaseJSONMarshaller.java:103) at com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.writeTo(JSONRootElementProvider.java:143) at 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.marshallToJSON(BaseJSONMarshaller.java:103) at com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.writeTo(JSONRootElementProvider.java:143) at 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.com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349) の handleRequest(WebApplicationImpl.java:1437) 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 org.apache.catalina.core.StandardHostValve.__invoke(StandardHostValve.java:161) の .core.StandardPipeline.invoke(StandardPipeline.java:595) org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java) でorg.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231) at com.sun.enterprise.v3.services.impl. com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195) の ContainerMapper$AdapterCallable.call(ContainerMapper.java:317) 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. com.sun の com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) の ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)。grizzly.ContextTask.run(ContextTask.java:71) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool. java:513) で java.lang.Thread.run(Thread.java:722) |#]

4

2 に答える 2

2

私はアンディとまったく同じ問題を抱えています。私が今までに見つけたのは:

@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 の初期化を強制します。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()は、プロキシのトリックやセッションの初期化は行われません。

任意のヒント?

編集:解決策

おそらく、ユーザーが何かをクリックしてアクションまたは 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 メソッドを呼び出すと、回答、質問、およびフィードバックが読み込まれて表示されます。

于 2012-11-11T16:51:29.570 に答える
0

LazyInitializationException: Session(そうでなければ : EntityManager) が閉じられた後、そのエンティティは切り離されます。QuestionFeedback問題は、オブジェクト ( 、QuestionCategoryおよび)のコレクションAnswerが切り離されていることです。lazy=falseで(Otherwise : FetchType.EAGER)を使用すると、が閉じられhibernateていてもオブジェクトのコレクションがメモリにロードされます。Session

参照 : Hibernate: レイジー フェッチを理解する

于 2012-11-11T10:47:38.703 に答える