18

Grailsでマルチスレッドアプリケーションを作成していますが、追加のスレッドはGORM/Hibernateにアクセスする必要があります。彼らがGORMにアクセスしようとすると、「org.hibernate.HibernateException:スレッドにバインドされたHibernateセッションがなく、構成ではここで非トランザクションセッションを作成できません」というエラーが表示されます。

十分に公平です。誰かがスレッドをアクセスできるように設定するための最良の方法を教えてもらえますか?エラーメッセージは、いくつかの設定オプションを変更する必要があるように聞こえますが、私は感じています、それはそれほど単純ではありません...

4

4 に答える 4

14

GORM呼び出しをwithTransactionクロージャーに入れる必要があります。https://fbflex.wordpress.com/2010/06/11/writing-batch-import-scripts-with-grails-gsql-and-gpars/でのマルチスレッドの議論からの例

シングルスレッド

user = User.findByUsername( photo.username )

マルチスレッド

User.withTransaction{
user = User.findByUsername( photo.username )
}
于 2010-08-24T13:07:39.093 に答える
14

Grailsアプリケーションには、これに使用できる「persistenceInterceptor」と呼ばれるBeanがあります。

使用方法については、JMSプラグインの次の例を参照してください。

http://github.com/gpc/grails-jms/blob/master/src/groovy/grails/plugin/jms/listener/adapter/PersistenceContextAwareListenerAdapter.groovy#L21

インターフェースは次のとおりです。

https://github.com/grails/grails-core/blob/master/grails-core/src/main/groovy/grails/persistence/support/PersistenceContextInterceptor.java

そしてHibernateimpl:

https://github.com/grails/grails-data-mapping/blob/master/grails-datastore-gorm-support/src/main/groovy/org/grails/orm/hibernate4/support/HibernatePersistenceContextInterceptor.java

于 2010-08-25T05:29:03.413 に答える
3

withNewSessionも機能します。私の場合、優先度の低い更新があり、最後の更新が常に「勝つ」ことができます。 version: falseStaleObjectExceptionを回避するために、ここでも重要です。

     Thread.start {
        try {
            Widget.withNewSession {
                xxx()
                log.info "Asynchronously did some updates."
            }
        } catch (Exception ex) {
            log.error "Failed to asynchronously do something...", ex
        }
    }
于 2017-02-09T04:16:39.570 に答える
1

ルーク・デイリーは正しい答えを出しました。残念ながら、リンクが変更されました。したがって、私は彼の答えを更新し、この答えを自己完結型にするためのコード例を提供します。

GrailsアプリケーションにはpersistenceInterceptor、Hibernateの永続コンテキスト/セッションを初期化するために使用できるBeanがあります。次のコードスニペットを使用して、Beanをコントローラー/サービスクラスの1つに挿入し、新しいスレッドを開始できます。

class YourControllerOrService {
    PersistenceContextInterceptor persistenceInterceptor
    
    def someOperation() {
        ...
        Runnable yourTask = { ->
            try {
                if (persistenceInterceptor) {
                    persistenceInterceptor.init()
                }
            
                // execute the hibernate operations here in a transaction,
                // e.g. call a method annotated with @Transactional
                ...
            } catch (Exception e) {
                    log.error('Your error message', e)
            } finally {
                if (persistenceInterceptor) {
                    persistenceInterceptor.flush()
                    persistenceInterceptor.destroy()
                }
            }
        }
        Thread workerThread = new Thread(yourTask)
        workerThread.start()
        ...
    }
}

GitHubのGrailsJMSプラグインに例示的な実装があります。

PersistenceContextInterceptorインターフェイスはGitHubにもあります。

于 2021-12-07T14:25:40.427 に答える