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 回答
3

withNewSession 也可以。就我而言,我的更新优先级较低,最后一次更新总是可以“获胜”。 version: false为了避免 StaleObjectException,这里也很重要:

     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 应用程序中有一个名为的 bean persistenceInterceptor,可用于初始化 Hibernate 的持久性上下文/会话。您可以将 bean 注入您的控制器/服务类之一并启动一个新线程,例如使用以下代码片段。

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 上的 Grails JMS 插件中找到示例性实现。

PersistenceContextInterceptor接口也可以在 GitHub 上找到。

于 2021-12-07T14:25:40.427 回答