3

Spring MVC 3.1.2 と Jackson 2 を使用しているというエラーに夢中になっています。

次のモデル クラスがあります。

@Entity
@Table(name = "USER")
@JsonIgnoreProperties(ignoreUnknown=true)
public class User implements Serializable
{
    @Id
    @SequenceGenerator(name = "USER_ID", sequenceName = "USER_ID_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_ID")
    private Long id;

    @Column(length = 50, nullable = false)
    private String firstName;

    @Column(length = 50, nullable = false)
    private String lastName;

    @ManyToMany
    @JoinTable(name = "FRIENDS",
        joinColumns = @JoinColumn(name = "personId"),
        inverseJoinColumns = @JoinColumn(name = "friendId")
    )
    @JsonManagedReference
    private List<User> friends;

    @ManyToMany
    @JoinTable(name="FRIENDS",
        joinColumns=@JoinColumn(name="friendId"),
        inverseJoinColumns=@JoinColumn(name="personId")
    )
    @JsonIgnore
    private List<User> friendOf;

    // Other attributes and methods... 
}

User の単一インスタンスを取得すると、Jackson によって正しくシリアル化されます。しかし、友人を含む User のインスタンスを取得しようとすると、次の例外がスローされます。

org.hibernate.LazyInitializationException: ロールのコレクションの遅延初期化に失敗しました: com.frooid.model.User.friends、セッションまたはセッションが閉じられませんでした

単一の HQL を使用してこのインスタンスを取得しています。

select u from User u left join fetch u.friends f where u.id = :id

みんなに感謝!

4

3 に答える 3

5

これOpenSessionInViewFilterは、ビュー内の遅延初期化フィールドにアクセスすることを目的としていますが、Jackson がコレクションにアクセスできるようにセッションを開いたままにしておくことができます。

OpenSessionInViewFilterは、リクエストの処理全体のために Hibernate セッションをスレッドにバインドします。「ビューでセッションを開く」パターンを対象としています。つまり、元のトランザクションが既に完了しているにもかかわらず、Web ビューで遅延読み込みを可能にするためです。

Web.xml 内

<filter>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

API ドキュメント

于 2012-11-25T20:20:45.753 に答える
5

ToMany アソシエーションはデフォルトで遅延ロードされます。これは、リストのメソッドを呼び出すときにのみ、ユーザーの友人がデータベースからロードされることを意味しますfriends

この遅延読み込みは、ユーザーの読み込みに使用されたセッションが開いているときにのみ発生します。したがって、フレンド リストをロードせずにトランザクション メソッドからユーザーを返すと、セッションが閉じられ、フレンド リストをロードしようとすると例外が発生します。

そのため、クライアントが友人リストをロードする必要がある場合は、HQL を使用して友人をフェッチするか、サービス メソッド内でリストのメソッドを呼び出すか、または を呼び出して、リストの初期化を強制しますHibernate.initialize(user.getFriends())

編集: HQL にフェッチがあるため、動作するはずです。もう 1 つの問題は、双方向の関連付けが 2 回マップされることです。フィールドfriends上で 1 回、フィールド上で 1 回friendOfです。mappedByこれらの関連付けの 1 つは、属性を使用して他の関連付けの逆としてマークする必要があります。

@ManyToMany(mappedBy = "friends")
@JsonIgnore
private List<User> friendOf;
于 2012-11-25T20:23:18.327 に答える
0

同様の問題がありました。アプローチは、新しいクラス(ビュー)を作成し@JsonView({NewClass1.class,NewClass2.class})、プロパティが定義されているエンティティで、各プロパティにこのクラスを追加することでした。応答の一部としてロードする変数を選択し、クラスを に含めることができます@JsonView。それと同じくらい簡単です!

于 2015-06-03T10:08:33.437 に答える