0

使用する必要のあるビジュアルパラダイムを使用してJavaプロジェクトを開発しています。VisualParadigmはHibernateを使用しています。Genady RMIを追加するまで、私のプロジェクトは正常に実行されていました。RMIも使用する必要があります。

サーバー側には、データベースへのすべてのクエリを管理するMainDbがあり、クライアント側には、RMIRemoteを実装するUserWindowクラスとAdminWindowクラスがあります。これらの2つのクラスは、RMIを介してオブジェクトMainDbを取得します。

サーバーとクライアントを実行しているときに、「セッションまたはセッションが閉じられていません」というエラーでレイジー初期化に関連する例外が発生しました。

failed to lazily initialize a collection of role: dcl.UsuarioRegistrado.ORM_TieneVideosFavoritos, no session or session was closed.

私の知る限り、Hibernateはdcl.UsuarioRegistradoオブジェクトが作成されたのとは別のセッションを使用しています。問題は、クラスPersistentManagerがgetSession()のみを提供するため、セッションを管理していないことです。クラスPersistentManagerは、Hibernateを管理するためにVisualParadigmによって提供されるクラスです。

すべてのエンティティをlazy="false"に構成しようとしましたが、一部のエンティティのプロパティが正しく読み込まれなかったため、結果が悪化しました。たとえば、オブジェクト「Topic」は、Stringプロパティ「TopicName」をnullとしてロードされました。

では、同じセッションを維持するために何ができるでしょうか?

よろしくお願いします。申し訳ありませんが、英語が下手です。英語で説明するのは難しいので、改めて感謝します。

4

1 に答える 1

1

これは一般的な問題です。エンティティにコレクションがある場合、Hibernate はインスタンスに「Hibernate 対応」コレクションを挿入します。したがって、リストの代わりに、現在のセッション (「現在」 = エンティティが読み込まれたセッション) を記憶するものを取得します。

その理由は、セッション == データベース トランザクションです。Hibernate が新しいセッションを使用して関連するエンティティをロードすると、親エンティティをロードしたときにまだ存在していた行が削除されたため、新しい行、更新された行が表示されるか、エラーが発生する可能性があります。それは混乱でしょう。

これが起こらないようにするために、Hibernate は元のセッションを使用してすべての関連エンティティをロードします。しかし、通常、コードは別の方法で動作します。ある部分では、エンティティをロードします。セッションは終了しました。そして、まったく関係のない部分で、子をロードしようとしました -> エラー。

次の 3 つの解決策があります。

  1. 遅延読み込みを無効にします。多くの場合、これは機能しません (ロードが多すぎる、遅すぎる)。ただし、エラーが発生することはありません。コードにバグが潜んでいる可能性があります。

  2. エンティティを読み込むときに、各コレクションから最初のエンティティを取得します。これにより、コレクションが適切に初期化されます。ここでの利点は、関連するインスタンスをロードするタイミングと、レイジー ロードに Hibernate を使用するタイミングをコードで決定できることです。

    必要なリレーションのみをロードすることもできます。これにより、前のポイントの問題が解決されることがよくあります。欠点は、他のコードがエンティティをどのように使用するかを事前に知る必要があることです。多くの場合、これは困難であるか、不可能ですらあります。

  3. Session.refresh()を使用して、新しいセッションを作成し、既存のオブジェクトをこの新しいセッションに「アタッチ」できます。ここでは注意が必要です。更新されたオブジェクトと古いオブジェクトを混在させると、エラーが発生します。

于 2012-08-28T12:34:06.217 に答える