如何将 Hibernate Session 绑定到 Grails 中的线程?
Posted
技术标签:
【中文标题】如何将 Hibernate Session 绑定到 Grails 中的线程?【英文标题】:How to I bind a Hibernate Session to a thread in Grails? 【发布时间】:2011-04-03 03:53:33 【问题描述】:我正在 Grails 中编写一个多线程应用程序,其他线程需要访问 GORM/Hibernate。当他们尝试访问 GORM 时,我收到错误“org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allowed create non-transactional one here”。
好吧,公平地说,有人可以指导我设置线程以进行访问的最佳方式吗?错误消息听起来就像您只需要更改一些配置选项,但我感觉,它并不那么简单......
【问题讨论】:
【参考方案1】: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
Hibernate 实现:
https://github.com/grails/grails-data-mapping/blob/master/grails-datastore-gorm-support/src/main/groovy/org/grails/orm/hibernate4/support/HibernatePersistenceContextInterceptor.java
【讨论】:
第二个链接坏了,是不是位置变了?【参考方案2】:您需要将任何 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 )
【讨论】:
这可能是偶尔线程使用最简单的方法了。【参考方案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
【讨论】:
这是我一直在寻找的答案。 方式比使用withTransaction
更好,如果您在后台进行一些您希望在进行时显示的更新。【参考方案4】:
Luke Daley 给出了正确答案。不幸的是,链接已更改。因此,我将更新他的答案并提供一个代码示例以使此答案自包含。
Grails 应用程序中有一个名为persistenceInterceptor
的bean,可用于为Hibernate 初始化持久性上下文/会话。您可以将 bean 注入您的控制器/服务类之一并启动一个新线程,例如使用以下代码 sn-p。
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()
...
您将在 Grails JMS plug-in on GitHub 中找到示例性实现。
PersistenceContextInterceptor 接口也可以在 GitHub 上找到。
【讨论】:
以上是关于如何将 Hibernate Session 绑定到 Grails 中的线程?的主要内容,如果未能解决你的问题,请参考以下文章
没有 Hibernate Session 绑定到线程,并且配置不允许在这里创建非事务性会话
Hibernate绑定session保证session为单线程操作
[原创]java WEB学习笔记94:Hibernate学习之路---session 的管理,Session 对象的生命周期与本地线程绑定