0

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

没有 Hibernate Session 绑定到线程,并且配置不允许在此处创建非事务性会话

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

编辑:
附加细节:我在线程中偶然发现了这篇帖子
Hibernate session

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

4

2 回答 2

4

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

  1. 您的服务在 grails-app 的服务目录中吗?
  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)

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

于 2010-12-31T23:57:11.700 回答
0

您需要为您的服务指定一个事务上下文。确保您的 Grails 服务以这种方式完成。

另一个 Grails 服务链接:

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

于 2010-12-31T22:57:50.273 回答