Hibernate Grails-如何在服务中保存域对象?

Hibernate Grails-如何在服务中保存域对象?,hibernate,session,grails,service,grails-domain-class,Hibernate,Session,Grails,Service,Grails Domain Class,我有一个服务,在其中一个函数中,我正在创建一个域对象并试图保存它。 当它到达保存部分时,我得到了错误 没有绑定到线程的休眠会话, 和配置不允许 在这里创建非事务性的 为了在服务中保存域对象,我需要做什么。互联网上的所有东西都让它看起来像这样,应该就行了 编辑: 其他详情: 我偶然发现了这篇文章 这是一个类似的场景。我的服务被第三方API调用 编辑: 我解释得不太清楚。下面是更完整的代码 import org.springframework.beans.factory.InitializingB

我有一个服务,在其中一个函数中,我正在创建一个域对象并试图保存它。
当它到达保存部分时,我得到了错误

没有绑定到线程的休眠会话, 和配置不允许 在这里创建非事务性的

为了在服务中保存域对象,我需要做什么。互联网上的所有东西都让它看起来像这样,应该就行了

编辑:
其他详情: 我偶然发现了这篇文章

这是一个类似的场景。我的服务被第三方API调用

编辑:
我解释得不太清楚。下面是更完整的代码

import org.springframework.beans.factory.InitializingBean
import com.ib.client.EWrapper;


class BrokerService implements InitializingBean, EWrapper{

    static transactional = true

    private EClientSocket m_client
    private boolean m_disconnectInProgress = false

    void afterPropertiesSet(){
       // this.setting = grailsApplication1.config.setting
       m_client = new EClientSocket(this)
       m_disconnectInProgress = false

       connect()
    }


    def boolean connect() {
        m_client.eConnect()
        if (m_client.isConnected())
            return true

        return false
 }

    def void historicalData(int reqId, String date, double open,
   double high, double low, double close, int volume, int count,
   double WAP, boolean hasGaps)
    {   
        HistoricalContractData.withNewSession{session->
            println ' just before object create'
            def hcd = new sbi.investments.HistoricalContractData()
            hcd.hc_id = reqId
            hcd.data_date = new Date().parse('yyyyMMdd', date.replace('finished-', ''))
            hcd.open = open
            hcd.high = high
            hcd.low = low
            hcd.close = close
            hcd.volume =volume
            hcd.trade_count =count
            hcd.wap = WAP
            hcd.has_gaps = hasGaps.toString()
            println ' just before save'
            hcd.save()

            if(hcd.hasErrors()){
                println '=========== ERROR! ============'
                println hcd.errors
            }
        }
 }
}
第三方API多次调用historicalData。使用上面的代码,它正在保存第一条记录,但在第二条记录上,我得到了错误:

无法打开休眠会话; 嵌套异常是 org.hibernate.SessionException: 会议结束了

编辑:
因此,我想通过更多的阅读了解正在发生的事情。
从控制器调用时,通常会将hibernate会话注入服务。
由于historicalData是从第三方应用程序调用的,而不是通过控制器调用的,因此服务中没有注入hibernate会话,因此它会抱怨会话已关闭

因此,我认为真正的问题可能是,如果没有从控制器调用服务,如何创建新的hibernate会话以保存grails域模型对象(即HistoricalContractData)。
如上所述,withNewSession不起作用。我应该这样使用SessionFactory吗?
(无法将链接发布到源,因为堆栈溢出不喜欢它)


我尝试过这样做,但不知道如何使用会话对象来保存HistoricalContractData对象。

您需要为您的服务指定一个事务上下文。确保您的Grails服务已经完成

另一个Grails服务链接:


您需要为您的服务指定一个事务上下文。确保您的Grails服务已经完成

另一个Grails服务链接:


默认情况下,服务方法应该是事务性的,并且有一个会话。如果不是这样,那么您可能没有遵循Grails约定:

  • 您的服务是否在grails应用程序的服务目录中
  • 您的服务名称/文件是否以“服务”结尾
  • 您是否以某种方式使服务或服务方法本身不是事务性的
  • 您不是从控制器调用服务吗
  • 您是否使用依赖注入将您的服务引入到您使用它们的地方
  • 也就是说,您始终可以通过执行以下操作来创建事务

    AnyDomainObject.withTransaction{txStatus->
    // do stuff like save here
    }
    
    或使用创建新会话

    AnyDomainObject.withNewSession{session->
    // do stuff here
    }
    
    您的代码没有闭包所需的“箭头”

    编辑,对于您的更新,您应该签出

    关于如何使用会话。基本上,你应该能够做到

    session.save(hcd)
    

    另外,在调用sessionFactory.getCurrentSession()之后,您可能可以像grails中的普通方法一样执行hcd.save()——我认为这可能有效的原因是,该方法应该创建一个新会话,并通过threadlocal将其绑定到当前线程

    默认情况下,服务方法应该是事务性的,并且具有会话。如果不是这样,那么您可能没有遵循Grails约定:

  • 您的服务是否在grails应用程序的服务目录中
  • 您的服务名称/文件是否以“服务”结尾
  • 您是否以某种方式使服务或服务方法本身不是事务性的
  • 您不是从控制器调用服务吗
  • 您是否使用依赖注入将您的服务引入到您使用它们的地方
  • 也就是说,您始终可以通过执行以下操作来创建事务

    AnyDomainObject.withTransaction{txStatus->
    // do stuff like save here
    }
    
    或使用创建新会话

    AnyDomainObject.withNewSession{session->
    // do stuff here
    }
    
    您的代码没有闭包所需的“箭头”

    编辑,对于您的更新,您应该签出

    关于如何使用会话。基本上,你应该能够做到

    session.save(hcd)
    

    另外,在调用sessionFactory.getCurrentSession()之后,您可能可以像grails中的普通方法一样执行hcd.save()——我认为这可能有效的原因是,该方法应该创建一个新会话,并通过threadlocal将其绑定到当前线程

    你是说服务范围吗?我的服务是单身。你能帮我指出一些例子或文件吗?感谢您帮助我更具体地了解您所说的“这种方式”是什么意思。我最初是按照那个教程创建我的服务的,但是关于这个主题的文档似乎很少。如果不查看您的所有代码,就无法更具体地说了。坦率地说,我不知道我想花时间。我今晚要出去!哈哈,很公平。谢天谢地,我也可以说我今晚要出去。明天我会发布更完整的代码。新年快乐!你是说服务范围吗?我的服务是单身。你能帮我指出一些例子或文件吗?感谢您帮助我更具体地了解您所说的“这种方式”是什么意思。我最初是按照那个教程创建我的服务的,但是关于这个主题的文档似乎很少。如果不查看您的所有代码,就无法更具体地说了。坦率地说,我不知道我想花时间。我今晚要出去!哈哈,很公平。谢天谢地,我也可以说我今晚要出去。明天我会发布更完整的代码。新年快乐@谢谢。我想我遵守了大多数惯例#4否,因为服务中的函数historicalData正在被第三方API(另一个应用程序)调用。@w-另一个应用程序如何获得您的服务?如果它通过web请求(例如RESTAPI)调用它,那么您应该在服务前面有一个控制器。不管怎样,如我所示添加箭头应该会有所帮助。@hvgotcodes,正如您所看到的