1

Spring Framework v3.2.4 と JPA + Hibernate 4 を使用して RESTful サービスを実装しています。JSON 形式でリソースを返していますが (Jackson Mapper を使用)、次の例外に悩まされています。

Could not write JSON: failed to lazily initialize a collection of role: it.teck.service.model.Canvas.params, could not initialize proxy - no Session (through reference chain: it.teck.service.model.Canvas["params"]);

CanvasParamエンティティの間に「多対多」の関係があり、キャンバスがサービスに要求されたときに params リストもシリアル化する必要があります。

私のクラスでは:

@Entity
public class Canvass {

    @ManyToMany
    @JoinTable(name = "canvas_params", joinColumns = { @JoinColumn(name = "id_canvas", referencedColumnName = "id_canvas") }, inverseJoinColumns = { @JoinColumn(name = "id_param", referencedColumnName = "id_param") })
        private List<Param> params;

    // ...
}

と:

@Entity
public class Param {

    @ManyToMany(mappedBy = "params")
    private List<Canvas> canvasList;

    // ...
}

いくつかの投稿では、ManyToManyフィールドをシリアライゼーションから除外し、シリアライゼーション ループを中断するというSO の回答が提案されていますが、キャンバス エンティティにリンクされたパラメーターをシリアライズする必要があります。それで、私は何をすべきですか?

4

5 に答える 5

4

これは、Jackson がセッション外で Hibernate によって管理されている Bean のプロパティにアクセスしようとしているために発生します。そのため、プロパティは遅延ロードされ、セッション外でアクセスしようとすると、hibernate は DB から取得できません。

次の 3 つのオプションがあります。

  1. イオンが言うように、エンティティに FetchType.EAGER を設定します。欠点は、この方法で 1 つのエンティティをフェッチするたびに、それにリンクされているすべての Canvas と Params をフェッチすることです。アプリの速度が低下する可能性があるため、これは望ましくない場合があります。
  2. DAO レベルまたはサービス レベルのセッションにまだいるときにシリアル化します。これが最もクリーンで適切な方法です
  3. 最後に、(まだセッション中に) params.size() や canvasList.size() などを実行すると、db からのコレクションのフェッチが自動的にトリガーされます。これはちょっとしたハックですが、機能し、エンティティの DAO 署名やフェッチ戦略を変更する必要はありません。

Spring には、シリアル化が行われるコントローラー メソッドを @Transactional にするという別のオプションがあります。これにより、セッションを開いたままにできます。ただし、メソッドがトランザクションになるため、望ましくない結果には注意してください。

于 2013-11-08T10:47:51.697 に答える
0

この問題を克服するために、実行時にフェッチ戦略を変更するには、以下を試すことができます。

User user = (User) session.createCriteria(User.class)
    .setFetchMode("permissions", FetchMode.JOIN)
    .add( Restrictions.idEq(userId) )
    .uniqueResult();

「FetchMode」にはさらにいくつかのオプションがあります。

于 2016-01-20T14:20:20.613 に答える