11

JPA が必要のないときにデータを遅延ロードしようとしているという問題があります。基本的に何が起こっているかというと、サービスを使用してデータを取得していて、そのデータを JSON に解析しようとすると、JSON ライブラリが休止状態をトリガーして、データを遅延ロードしようとします。これを止める方法はありますか?以下に例を示しました。

// Web Controller method
public String getEmployeesByQuery(String query) {

    Gson gson = new Gson();
    List<Employee> employees = employeeService.findEmployeesByQuery(query);

    // Here is where the problem is occurring - the gson.toJSON() method is (I imagine)
    // using my getters to format the JSON output, which is triggering hibernate to
    // try and lazily load my data...
    return gson.toJSON(employees);
}

データを遅延ロードしようとしないように JPA/hibernate を設定することは可能ですか?

更新: FetchType.EAGER を使用できることはわかっていますが、そのデータを積極的にロードしたくない場合はどうすればよいでしょうか? 休止状態がより多くのデータを取得しようとするのを止めたいだけです-必要なデータは既にあります。現在、get() メソッドにアクセスしようとすると、休止状態で「セッションがないか、セッションが閉じられていません」というエラーがスローされます。これは、トランザクションがサービスから既にコミットされているためです。

ありがとう!

4

8 に答える 8

6

いくつかのオプションがあります:

  • コレクションを熱心にロードする必要がある場合fetch = FetchType.EAGERは、他の回答で提案されているように、マッピングで指定できます。

  • それ以外の場合は、特定のクエリに対して熱心なフェッチを有効にすることができます。

    • JOIN FETCHHQL/JPQL クエリで句を 使用することにより:

      SELECT e FROM Employee e JOIN FETCH e.children WHERE ...
      
    • フェッチ プロファイルを使用する (JPA では、Session経由でHibernate にアクセスできますem.unwrap(Session.class))
于 2011-01-26T15:01:32.463 に答える
3

実際には 2 つのオプションがあります。

  1. 従業員から休止状態によってプロキシされていない従業員にデータをコピーできます。
  2. toJSONオブジェクト グラフ全体をライブラリに反映させない方法があるかどうかを確認してください。一部の JSON ライブラリでは、オブジェクトの一部のプロパティのみを JSON にシリアル化できることを知っています。

個人的には、ライブラリがリフレクションのみを使用している場合、#1 の方が簡単だと思います。

于 2011-01-26T15:47:18.367 に答える
2

他の人が述べているように、これは JPA/hibernate の問題ではなく、使用している json シリアル化ライブラリの問題です。トラバースしたくないプロパティを除外するように gson に指示する必要があります。

于 2011-01-26T20:04:49.393 に答える
1

トランザクションの外で使用したいエンティティのフェッチされたコピーを作成することをお勧めします。そうすれば、トランザクション内から遅延読み込みが発生し、拡張されていないプレーンな POJO を Gson に渡すことができます。

Doozerを使用してこれを行うことができます。これは非常に柔軟で、ちょっとした設定 (設定で髪が緩んでしまうことをお読みください) によって、Gson に送信したいデータの一部のみを取得することさえできます。

于 2011-01-26T15:41:12.003 に答える
1

はい:

@*ToMany(fetch=FetchType.EAGER)
于 2011-01-26T14:44:32.333 に答える
0

問題は、データをシリアル化することです。FlexとJPA/Hibernateでも同じような問題が発生しました。秘訣は、物事をどれだけ壊したいかに応じて、どちらかです

  1. 不要なデータを追跡しないようにデータモデルを変更します。
  2. 必要なデータを、関係のないある種のDTOにコピーします。
  3. Hibernateを使用していると仮定して、Session-in-viewフィルターを追加します....そのようなもので、データベース全体をシリアル化する間、セッションを開いたままにします。;)

オプション1は、最初に行った大きなプロジェクトで行ったことですが、あらゆる種類の汎用用途で使用していたデータアクセスライブラリを台無しにしました。それ以来、私たちはオプション2に向かう傾向がありました。

YMMV

于 2011-01-26T16:39:08.607 に答える
0

いつでもfetch属性をFetchType.EAGERに変更できますが、トランザクションに適切なスコープがあるかどうかも検討する価値があります。コレクションがトランザクション内でアクセスされる場合、コレクションは正しくロードされます。

于 2011-01-26T14:47:42.500 に答える
0

簡単で簡単なことは、新しいデータ クラス (DTO のようなもの) を作成し、Hibernate.isInitialized() を使用して、オブジェクトが hibernate によって初期化されているかどうかを確認することです。何かをオーバーライドできるかどうか、gson をチェックしています。新しいものを見つけたら、ここに投稿します。

于 2011-07-27T13:24:11.610 に答える