无法打开Hibernate Session进行事务处理

时间:2011-09-20 15:40:12

标签: grails

我正在开发一个grails应用程序(服务器)来跟踪Wi-Fi网络中的移动设备。用户将向grails应用程序(服务器)上运行的Web服务发送请求以及Mobileid和Wi-Fi IP地址。

在我的grails应用程序中,我正在查看多个外部java线程,每个线程将ping每个移动设备的Wi-Fi IP地址(每个设备要跟踪一个线程)。如果无法访问任何设备IP,那么我将从外部线程将数据库中的移动状态更新为“已断开连接”。这里只有我遇到问题,如果多个设备无法访问,那么多个线程将使用 domain.withTransaction 方法更新同一个表中每个设备的状态,而我正在获取以下异常

org.springframework.transaction.CannotCreateTransactionException:无法打开Hibernate Session进行事务处理;嵌套异常是java.lang.NullPointerException     在org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:596)     在org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager.super $ 3 $ doBegin(GrailsHibernateTransactionManager.groovy)     at sun.reflect.GeneratedMethodAccessor492.invoke(Unknown Source)     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)     在java.lang.reflect.Method.invoke(Method.java:597)     在org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:88)     at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)     at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1058)     at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1070)     在org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuperN(ScriptBytecodeAdapter.java:127)

我的代码:

在线程中ping设备

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天,但我无法解决这个问题。

3 个答案:

答案 0 :(得分:3)

将读取移动到事务中,否则它们将处于断开连接的会话中,而不是事务创建的会话中。此外,最好在类上调用静态方法,而不是实例(在Groovy和Java中):

void deviceDisconnected(String mobileId, String wifiIp){
   try {
      UserMobile.withTransaction { tx ->
         def mobile = Mobile.findByMobileId(mobileId)
         def userMobile = UserMobile.findByMobileAndWifiIp(mobile, wifiIp)
         userMobile.action = Constants.MOBILE_STATUS_DISCONNECTED
         userMobile.alarmStatus = Constants.ALARM_STATUS_TURNED_ON
         userMobile.modifiedDate = new Date()
         userMobile.save(flush: true)
      }
   }
   catch(e) {
      e.printStackTrace()
   }
}

答案 1 :(得分:1)

而不是使用Tiggerizzy建议的详细绑定代码。最好在域类上使用内置的withNewSession方法:

Mobile.withNewSession {
   // your code here
}

答案 2 :(得分:0)

我不需要传播错误信息和糟糕的做事方式。 Burt和Graeme的答案都有效。我刚写了quick test app to prove this