2011-08-02 9 views
5

コントローラの1つで遅延ロードの問題が発生することがあります。 注:私はOpenSessionInViewInterceptorを使用していて、私の "サービス"レイヤにTransactionalという注釈を付けています。Spring + Hibernate遅延ロードエラー

私はPersonオブジェクトを読み込むために、キーとSSNの2つの方法があります。私の人物のオブジェクトには、私は遅れてロードするロールのコレクションを持っています。私がキーでロードするとき、私は期待どおりリストにアクセスすることができます。 SSNでロードすると、リストにアクセスできません。

私が追加した私のサービス層構成ファイルで

:ここ

<tx:annotation-driven /> 

キー& SSNによって人をロードし、私のサービス層ピースは(私はこれがDAO /再編にする必要があります知っている - この継承されたコード)がある - SSNピースでもないバージョンをメモロードを可能にする - の両方が同じクラスにあります。

@Transactional(readOnly = true, propagation = Propagation.REQUIRED) 
public Person loadPersonByKey(final Person.Key personKey) { 
    Assert.notNull(personKey); 
    return (Person) getHibernateTemplate().get(Person.class, personKey); 
} 

@Transactional(readOnly = true, propagation = Propagation.REQUIRED) 
public Person findPersonBySsn(final SocialSecurityNumber ssn) { 

    @SuppressWarnings("unchecked") 
    //List<Person> results = getHibernateTemplate().findByNamedParam("from core.model.entities.Person as person where ssn = :ssn", "ssn", ssn); 

    Criteria crit = getSession().createCriteria(Person.class); 
    crit.add(Restrictions.eq("ssn", ssn)); 
    List<Person> results = crit.list(); 

    int size = results.size(); 

    Person returnPerson = ((size != 0) ? (Person) results.get(0) : null); 
    return returnPerson; 
} 

私のコントローラの唯一の違いは、SSNによってキーによる1つの負荷、および1つの負荷です。ここではスタックトレースの要部である:

SEVERE: Servlet.service() for servlet springmvc threw exception 
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: core.model.entities.Person.memberships, no session or session was closed 
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383) 
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375) 
at org.hibernate.collection.AbstractPersistentCollection.readElementByIndex(AbstractPersistentCollection.java:176) 
at org.hibernate.collection.PersistentMap.get(PersistentMap.java:169) 
at core.model.entities.Person.getMemberships(Person.java:870) 
at core.springmvc.controllers.find.FindController.defaultAction(FindController.java:164) 

奇数のノートは、私はすぐにSSNでロードした後、キーで人をロードする場合、私は問題なく収集を読むことができますよ。

編集:ここでは

前のスタックトレースをログです:

2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.springframework.jdbc.datasource.DataSourceUtils CV#905cde28-e60c-4331 P#75004 - Resetting read-only flag of JDBC Connection [Transaction-aware proxy for target Connection [jdbc:oracle:thin:@(description=(address_list=(address=(host=127.0.0.1)(protocol=tcp)(port=11523))(load_balance=yes)(failover=yes))), UserName=USER_NAME, Oracle JDBC driver]] 
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.hibernate.impl.SessionImpl CV#905cde28-e60c-4331 P#75004 - disconnecting session 
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.hibernate.jdbc.ConnectionManager CV#905cde28-e60c-4331 P#75004 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] 
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.springframework.jdbc.datasource.DataSourceUtils CV#905cde28-e60c-4331 P#75004 - Returning JDBC Connection to DataSource 
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.hibernate.jdbc.ConnectionManager CV#905cde28-e60c-4331 P#75004 - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! 
+0

また、Hibernate.initialize(person)を呼び出すと、初期化例外が発生します。これはサービスレイヤでも同じことです。 – Scott

答えて

2

あなたは例外がどこから来ている見にスタックトレースを十分に示さなかったが、私はそれが中だと仮定あなたのビューレイヤー。これは、ビューパターンでのオープンセッションについてです。あなたはOpenSessionInViewInterceptorを使用していると言いますが、明らかに十分な範囲を与えているわけではありません。インターセプタはメソッド呼び出しに適用されます。私はあなたがあなたの "サービス"にそれを適用したと推測します。もしそうなら、それをオフにするだけでもいいかもしれません。あなたのために何もしません。パターンの全体のポイントは、セッションが開かれたままになるようにすることです。を超えて、サービスレイヤの境界はです。一般的なWebアプリケーションの場合は、OpenSessionInViewFilterが適切です。

+0

次の2行のスタックトレースを追加しました。それは間違いなくビューの内側で起こっていません。 – Scott

+0

@Scott:コントローラーを「ビュー」にグループ化します。 OpenSessionInViewInterceptorはどこに適用されますか? –

+0

標準OpenSessionInViewInterceptorを使用しています。これは、Dispatcherサーブレットを介して処理されるすべての要求に適用されます。私が動作しているコントローラと動作していないコントローラを介してデバッグすると、インターセプタが利用しているセッションがあることがわかります。何かが誤って設定されていなければなりません。私の遅延ロードされたコレクションを囲むHibernateがデバッグ時にセッションを表示しない永続的なコレクションです。 – Scott

関連する問題