12

Foo にはこれが含まれているように見えます:

@ManyToMany
private Set<User> favouritedBy;

ユーザーがこれを持っている間:

@ManyToMany(mappedBy = "favouritedBy")
private Set<Foo> favourites  = new HashSet<Foo>();
public Set<Foo> getFavourites() {
  return favourite;
}

そして fooService にはこれがあり、セッションが開かれている間に遅延ロードされたコレクションがトランザクションメソッドを介してアクセスされます:

@Transactional(readOnly = true)
public Set<Foo> getFavourites(User user) {
user = dao.get(User.class, user.getId()); //the dao gets a session
Set<Foo> favourites = user.getFavourites();//but the session is not here and the exception is thrown?
return  favourties;
}

EDIT これは、基準を使用せずに修正します:

Set<Foo> favourites = new HashSet<Foo>(user.getFavourites());

これにより、基準で修正されます

Session session = sessionFactory.getCurrentSession();
final Criteria crit = session.createCriteria(Foo.class);
crit.setFetchMode("favourites", FetchMode.JOIN);
crit.add(Property.forName("id").eq(id));
return (Foo) crit.uniqueResult();
4

4 に答える 4

13

FetchTypeaのデフォルトManyToManyはであり、レイジー アソシエーションLAZYを操作するための hibernate のドキュメントでは、この種のアクセスはエラーとして明確に指摘されています。セッションがまだ開いている間のみ、遅延関連付けされたオブジェクトを操作できます。ドキュメントのその部分では、オブジェクトのそのような遅延関連付けされたメンバーにアクセスするための代替手段も提供しています。私たちのアプリケーションでは、使用される基準のようにフェッチ モードを指定することを好みます。JOIN

編集

Set<Foo> favourites = user.getFavourites();

Foo上記のステートメントは、実際にはすべてのオブジェクトを含むセットを返しません。それは単なるプロキシです。実際のFooオブジェクトは、セット内の要素がアクセスされた場合favorites.iterator()などにのみフェッチされます。この操作は明らかにgetFavorites()メソッドの外部で行われています。ただし、メソッドの@Transactional注釈はgetFavorites()、このメソッドの最後でセッションが閉じられることを示しています。

したがって、お気に入りセットでメソッドが呼び出されると、セッションはすでに閉じられているため、例外が発生します。

これに対処するには、Criteria オブジェクトを使用してユーザーを取得し、フェッチ タイプを指定して、JOIN返された User オブジェクトに Foo オブジェクトが取り込まれるようにする必要があります。

于 2012-12-02T16:27:51.773 に答える
9

解決策は 2 つあります。

  1. 遅延ロードを使用しないでください。

    Set lazy=falsein XML または Set @OneToMany(fetch = FetchType.EAGER)In アノテーション。

  2. 遅延ロードを使用します。

    Set lazy=truein XML または Set @OneToMany(fetch = FetchType.LAZY)In アノテーション。

    フィルターを追加しますweb.xml

     <listener>
         ...
     </listener>
     <filter>
         <filter-name>hibernateFilter</filter-name>
         <filter-class>
             org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
         </filter-class>
         <init-param>
             <param-name>sessionFactoryBeanName</param-name>
             <param-value>mySessionFactory</param-value> 
         </init-param>
     </filter>
     <filter-mapping>
         <filter-name>hibernateFilter</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
     <servlet>
         ...
     </servlet>
    

そして<param-value>mySessionFactory</param-value>、で定義されたsessionFacory Bean名ですapplicationContext.xml

于 2014-12-04T04:14:52.233 に答える
2

はい、トランザクション コンテキストでオブジェクトにアクセスする必要があります。そうしないと、操作で がスローされますLazyInitializationException

于 2013-11-21T17:01:46.473 に答える