0

本番サーバーのgrailsアプリケーションで、いくつかの問題が発生しました。securityFiltersで、springSecurityServiceを注入していて、ある時点で次のような質問をしています。

if(springSecurityService?.currentUser?.client){
...
}

しかし、システムは次のようにエラーをスローします

Error 500: Internal Server Error
Class
org.hibernate.LazyInitializationException
Message
could not initialize proxy - no Session
Trace
   Line | Method
->>  32 | doCall            in SecurityFilters$_closure1_closure2_closure4
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    82 | doFilterInternal  in com.linkedin.grails.profiler.ProfilerFilter
|   190 | invoke . . . . .  in org.apache.jk.server.JkCoyoteHandler
|   291 | invoke            in org.apache.jk.common.HandlerRequest
|   776 | invoke . . . . .  in org.apache.jk.common.ChannelSocket
|   705 | processConnection in     ''
|   898 | runIt . . . . . . in org.apache.jk.common.ChannelSocket$SocketConnection
^   636 | run               in java.lang.Thread

32行目は、上記のifステートメントを呼び出す場所です。このLazyInitializationExceptionを解決する方法の手がかりはありますか?私が間違っていることは何ですか?

注:「client」は、このユーザーが属するドメインクラスですが、PersonのbelongsToパラメーターには記載されていません。

ありがとう。

4

2 に答える 2

3

イベントはコントローラーのHibernateセッションの外部で実行されるため、ユーザーをロードするとすぐに切断され、遅延ロードされたコレクションまたは多対1の参照は解決されません。これを修正する最も簡単な方法は、ユーザーのロード呼び出しをwithTransactionブロックでラップすることです。これにより、Hibernateセッションが常に開いたままになります。

AnyDomainClass.withTransaction { status ->
   if (springSecurityService?.currentUser?.client) {
      ...
   }
}
于 2012-11-07T15:36:36.453 に答える
0

ドメインオブジェクトがどこでも正しく機能するようにするには、レイジープロパティを使用することをお勧めします。あなたのオブジェクトがどのように見えるかはわかりませんが、何らかのオブジェクト関係がある場合は、それらを非遅延にすることができます。ちょうどこのような:

class Card {
  static hasMany = [cardProperties: CardProperty]
  static mapping = {
    cardProperties lazy: false
  }
}

利用可能なセッションを確実に確保するために、トランザクションサービスを作成することをお勧めします。どのサービスでもかまいませんが、行が含まれていないことを確認してください

static transactional = false

そのサービスをフィルターに注入すると、トランザクションが自動的に作成され、遅延プロパティをフェッチできるようになります。しかし、注意してください!これにより、トランザクションが開始および終了します。フィルタで使用するため、ページの読み込みには1つのトランザクションが追加されます。

もう1つのオプションは、sessionFactoryBeanをフィルターに注入することです。次に、純粋なHibernate構文を使用できます。これと同じように:

sessionFactory.getCurrentSession().beginTransaction();

それはあまり良い考えではありません、そして私はそれを忠告しません、しかしそれはあなたのために働くかもしれません。ただし、リクエストを転送すると、トランザクションが2回開かれ、トランザクションが2回閉じられることに注意してください(これは問題ありません)。トランザクションをコミットするかどうかを決定するときは、非常に注意する必要があります。ただし、アプリのすべてのページでデータベース接続が必要であると確信している場合は、それでうまくいく可能性があります/

于 2012-11-07T15:16:38.787 に答える