Grails 无法打开事务的休眠会话
我正在开发一个grails应用程序(服务器),用于跟踪Wi-Fi网络中的移动设备。用户将向运行在grails applicion(服务器)上的Web服务发送请求,同时发送Mobileid和Wi-Fi IP地址 在我的grails应用程序中,我启动了多个外部java线程,每个线程将ping每个移动设备的Wi-Fi IP地址(每个设备跟踪一个线程)。如果无法访问任何设备IP,则我将从外部线程将数据库中的移动状态更新为“已断开”。这里只有我面临的问题,如果多个设备处于不可访问状态,那么多个线程将使用域更新同一表中每个设备的状态 org.springframework.transaction.CannotCreateTransactionException:无法为事务打开Hibernate会话;嵌套异常是java.lang.NullPointerException 位于org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:596) 位于org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager.super$3$doBegin(GrailsHibernateTransactionManager.groovy) 位于sun.reflect.GeneratedMethodAccessor492.invoke(未知源) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)中 位于java.lang.reflect.Method.invoke(Method.java:597) 位于org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:88) 位于groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) 位于groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1058) 位于groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1070) 位于org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuperN(ScriptBytecodeAdapter.java:127) 我的代码: 线程中的ping设备Grails 无法打开事务的休眠会话,grails,Grails,我正在开发一个grails应用程序(服务器),用于跟踪Wi-Fi网络中的移动设备。用户将向运行在grails applicion(服务器)上的Web服务发送请求,同时发送Mobileid和Wi-Fi IP地址 在我的grails应用程序中,我启动了多个外部java线程,每个线程将ping每个移动设备的Wi-Fi IP地址(每个设备跟踪一个线程)。如果无法访问任何设备IP,则我将从外部线程将数据库中的移动状态更新为“已断开”。这里只有我面临的问题,如果多个设备处于不可访问状态,那么多个线程将使用域
try {
final InetAddress inet = InetAddress.getByName(ipAddress);
boolean status = inet.isReachable(5000);
if (status) {
pool.run(MobileDeviceTracker.deviceMap.get(mobileId));
} else {
// Calling service to update the status of device as disconnected
getUserMobileService().deviceDisconnected(mobileId, ipAddress);
}
} catch (Exception e) { }
更新数据库中的状态
class DisconnectionService implements UserMobileServiceInt{
static transactional = true
def void deviceDisconnected(String mobileId, String wifiIp){
try{
def mobile = Mobile.findByMobileId(mobileId)
def userMobile = UserMobile.findByMobileAndWifiIp(mobile, wifiIp)
userMobile.withTransaction {tx ->
userMobile.action = Constants.MOBILE_STATUS_DISCONNECTED
userMobile.alarmStatus = Constants.ALARM_STATUS_TURNED_ON
userMobile.modifiedDate = new Date()
userMobile.save(flush: true)
}
}catch(Exception e){
e.printStackTrace()
}
我在最后4天尝试,但无法解决此问题。将读取内容移动到事务中,否则它们将处于断开连接的会话中,而不是事务创建的会话中。另外,最好在类上调用静态方法,而不是在实例上(在Groovy和Java中):
将读取移动到事务中,否则它们将处于断开连接的会话中,而不是事务创建的会话中。另外,最好在类上调用静态方法,而不是在实例上(在Groovy和Java中):
我不需要传播错误的信息和糟糕的做事方式。伯特和格雷姆的答案都会奏效。我刚刚写了一篇文章。我不需要传播错误的信息和糟糕的做事方式。伯特和格雷姆的答案都会奏效。我只是写了一个.而不是使用Tiggerizzy建议的冗长绑定代码。最好在域类上使用内置的withNewSession方法:
Mobile.withNewSession {
// your code here
}
而不是使用Tiggerizzy建议的详细绑定代码。最好在域类上使用内置的withNewSession方法:
Mobile.withNewSession {
// your code here
}
当我使用Domain.withNewSession时,我遇到以下异常:org.springframework.dao.DataAccessResourceFailureException:无法打开Hibernate会话;嵌套异常为org.hibernate.SessionException:会话已关闭!位于org.springframework.orm.hibernate3.SessionFactoryUtils.getNewSession(SessionFactoryUtils.java:527),位于org.springframework.orm.hibernate3.HibernateTemplate.getSession(HibernateTemplate.java:454),位于org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:393)@EaswaramoorthyKanagaraj的代码听起来像是运行在一个不是由Grails创建的线程上,因此没有上下文来创建一个线程。使用我建议的冗长且不完美的代码或Executor插件是在随机线程上实现hibernate会话的最佳方法。当我使用Domain.withNewSession时,我遇到以下异常:org.springframework.dao.DataAccessResourceFailureException:无法打开hibernate会话;嵌套异常为org.hibernate.SessionException:会话已关闭!位于org.springframework.orm.hibernate3.SessionFactoryUtils.getNewSession(SessionFactoryUtils.java:527),位于org.springframework.orm.hibernate3.HibernateTemplate.getSession(HibernateTemplate.java:454),位于org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:393)@EaswaramoorthyKanagaraj的代码听起来像是运行在一个不是由Grails创建的线程上,因此没有上下文来创建一个线程。使用我建议的冗长且不完美的代码或Executor插件是在随机线程上实现hibernate会话的最佳方法。@Burt:我还是遇到了同样的异常。这是由于多个线程之间使用相同的hibernate会话造成的吗?如果是这样的话,有没有办法在grails中增加hibernate会话的创建?我没有为hibernate配置任何东西?你能告诉我grails中hibernate的更好配置吗?不,这就是全部问题所在-hibernate会话在新线程中不可用。但是使用
with transaction
(即使您没有更新)是一个快速修复方法,因为它创建并绑定一个新会话,并在整个过程中保持加载的实例的连接。能否尝试grails clean
并再次运行?@BurtBeckwith除非最近(2.0?)发生了变化,否则withNewSession和withTransaction都不会在新创建的线程上绑定或创建hibernate会话。这就是为什么Executor插件和它之前的后台线程插件存在的原因。不,不是真的withTransaction
总是这样做。我经常建议将其作为解决此类问题的一种方法,即使您不更新数据库,因为创建tx是相对轻量级的withNewSession
较新,但如果它可用,可能会更好,因为它确实绑定了sess