【问题标题】:Grails - how to save a domain object inside a Service?Grails - 如何在服务中保存域对象?
【发布时间】:2010-12-31 22:45:45
【问题描述】:

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

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

为了将域对象保存在服务中,我需要做什么。互联网上的所有内容看起来都应该可以正常工作....

编辑:
额外细节: 我偶然发现了这篇文章
Hibernate session in threads

这是一个类似的场景。我的服务被第 3 方 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
            }
        }
 }
}

第 3 方 API 多次调用 historyData。使用上面的代码,它正在保存第一条记录,但是在第二条记录上我得到了错误:

无法打开休眠会话; 嵌套异常是 org.hibernate.SessionException: 会话已关闭!

编辑:
所以阅读更多我想我明白发生了什么。
当从控制器调用时,通常会将休眠会话注入到服务中。
因为historyData 是从第三方应用程序而不是通过控制器调用的,所以没有休眠会话被注入到服务中,因此它抱怨会话已关闭。

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

import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class YourService  {

    SessionFactory sessionFactory // set by Dependency Injection

    public void yourMethod() {
        Session session = sessionFactory.getCurrentSession();
        // do something with session
    }
}

我尝试过,但不明白如何使用会话对象来保存 HistoricalContractData 对象。

【问题讨论】:

    标签: hibernate session grails service grails-domain-class


    【解决方案1】:

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

    1. 您的服务是否在 grails-app 的 services 目录中?
    2. 您的服务名称/文件是否以“服务”结尾?
    3. 您是否使服务或服务方法本身不是事务性的?
    4. 您不是从控制器调用服务吗?
    5. 您是否使用依赖注入将您的服务放到您使用它们的任何位置?

    也就是说,您总是可以通过以下方式创建交易

    AnyDomainObject.withTransaction{txStatus->
    // do stuff like save here
    }
    

    或创建一个新会话

    AnyDomainObject.withNewSession{session->
    // do stuff here
    }
    

    您拥有的代码没有闭包所需的“箭头”。

    编辑,为你更新,你应该结帐

    http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html

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

    session.save(hcd)
    

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

    【讨论】:

    • @hvtgotcodes 谢谢。我想我正在遵循大多数约定。 #4 否,因为服务中的函数 historyData 被第 3 方 API(另一个应用程序)调用。
    • @w- 其他应用程序如何获得您的服务?如果它通过 Web 请求(例如 REST api)调用它,那么您应该在服务前面有一个控制器。无论如何,添加我显示的箭头应该会有所帮助。
    • @hvgotcodes 如您所见,该服务实现了 EWrapper,这是一个由 3rd 方 API 提供的接口。 “HistoricalData”被注册为其他应用程序用来给我数据的回调函数。因此服务不会通过来自控制器的 HTTP 请求被调用。它只是被……直接调用。这有助于澄清吗?
    • @w- HistoricalContractData 是域模型类吗?
    • @hvtgotcodes 是的。所以阅读更多我想我理解可能发生的事情。请查看上面更新的 cmets,如果我完全偏离轨道,请告诉我。谢谢。
    【解决方案2】:

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

    另一个 Grails 服务链接:

    http://www.grails.org/doc/1.0.x/guide/8.%20The%20Service%20Layer.html

    【讨论】:

    • 您是指服务范围吗?我的服务是单身人士。你能帮我指出一些例子或文档吗?谢谢
    • 您能否更具体地了解您所说的“这种方式”是什么意思?
    • 如果没有看到你所有的代码就不能更具体了。坦率地说,我不知道我想花时间。我今晚要出去!
    • 哈哈公平。谢天谢地,我也可以说我今晚要出去了。明天我会发布更完整的代码或其他东西。新年快乐!
    猜你喜欢
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 2020-01-01
    • 1970-01-01
    • 2014-06-07
    相关资源
    最近更新 更多