我有一个服务,其中一个函数我正在创建一个域对象并试图保存它 当它到达保存部分时,我收到错误
没有Hibernate Session绑定到线程, 和配置不允许 在这里创建非交易的
为了在服务中保存域对象,我需要做什么。互联网上的一切都让它看起来像是应该工作....
修改
额外细节:
我偶然发现了这篇文章
Hibernate session in threads
这是一个类似的场景。我的服务正在被第三方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。使用上面的代码,它保存了第一条记录,但是在第二条记录上我得到了错误:
无法打开Hibernate Session; 嵌套异常是 org.hibernate.SessionException: 会议已结束!
修改
所以阅读更多我认为我明白发生了什么
当从控制器调用时,通常会向服务中注入一个休眠会话
因为历史数据是从第三方应用程序而不是通过控制器调用的,所以没有将hibernate会话注入服务,因此它会抱怨会话已关闭。
所以我认为真正的问题可能是,如果没有从控制器调用服务,我如何创建一个新的hibernate会话以保存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对象。
答案 0 :(得分:4)
默认情况下,服务方法应该是事务性的,并且具有会话。如果不是,你可能不会以某种方式遵循Grails惯例:
也就是说,您可以通过
创建交易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将其绑定到当前线程。
答案 1 :(得分:0)
您需要为服务指定交易上下文。确保您的Grails服务已完成this way。
另一个Grails服务链接:
http://www.grails.org/doc/1.0.x/guide/8.%20The%20Service%20Layer.html