Grails - 如何在服务中保存域对象?
我有一项服务,在其中一个函数中我正在创建一个域对象并尝试保存它。
当它到达保存部分时,我收到错误
没有 Hibernate 会话绑定到线程, 并且配置不允许 在这里创建非事务性的
我需要做什么才能将域对象保存在服务中。互联网上的所有内容都使它看起来应该可行......
编辑:
其他详细信息: 我偶然发现了这篇文章
线程中的 Hibernate 会话
这是一个类似的场景。我的服务被第三方 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 多次调用历史数据。使用上面的代码,它保存第一条记录,但在第二条记录上我收到错误:
无法打开休眠会话; 嵌套异常是 org.hibernate.SessionException: 会议已结束!
编辑:
因此,更多地阅读此内容,我想我明白发生了什么。
当从控制器调用时,休眠会话通常会注入到服务中。
由于历史数据是从第三方应用程序调用的,而不是通过控制器调用的,因此没有休眠会话被注入到服务中,因此它会抱怨会话已关闭。
所以我认为真正的问题可能是,如果没有从控制器调用服务,我如何创建一个新的休眠会话以保存 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 对象。
I have a service and inside one of the functions i'm creating a domain object and trying to save it.
when it gets to the save part, i get the error
No Hibernate Session bound to thread,
and configuration does not allow
creation of non-transactional one here
What do i need to do in order to save a domain object inside of a service. everything on the internet makes it look like this should just work....
Edit:
additional details:
I stumbled across this post
Hibernate session in threads
which is a similar scenario. My service is getting called by a 3rd party API.
Edit:
I'm not explaining this very well. Here is more complete code
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
}
}
}
}
the 3rd party API is calling historicalData several times. With the above code, it is saving the first record, but then on the 2nd record i'm getting the error:
Could not open Hibernate Session;
nested exception is
org.hibernate.SessionException:
Session is closed!
Edit:
so reading up on this more i think i understand what is happening.
a hibernate session is usually injected into the Service when called from the controller.
Because historicalData is being called from a 3rd party app and not via a controller, no hibernate session is getting injected into the service so it complains that the Session is closed.
So I think the real question may be, if a service is not called from a controller, how do i create a new hibernate session in order to save a grails domain model object (i.e. HistoricalContractData).
As can be seen above, withNewSession is not working. Should i be using a SessionFactory like so ?
(can't post link to source because stack overflow doesn't like it)
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
}
}
I kind of tried this but don't understand how to use the session object in order to save the HistoricalContractData object.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
默认情况下,服务方法应该是事务性的,并且具有会话。如果不是,您可能没有遵循 Grails 约定:
也就是说,您始终可以通过使用
执行或创建一个新会话
您拥有的没有关闭所需的“箭头”的代码
来创建事务。编辑,对于您的更新,您应该签出
http: //docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html
了解如何使用会话。基本上,你应该能够做到这一点
此外,你可能能够像在grails中一样在你调用sessionFactory.getCurrentSession()之后执行hcd.save() - - 我认为这可能有效的原因是该方法应该创建一个新会话并通过 threadlocal 将其绑定到当前线程。
Service methods should be transactional, and have a session, by default. If they are not, you are probably not following Grails conventions somehow:
That said, you can always create a transaction by doing
or create a new session with
the code you have does not have the 'arrow' that is necessary for closures.
EDIT, for you updates, you should checkout
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html
on how to use the session. Basically, you should be able to do just
Also, you might be able to do hcd.save() like normal in grails after you call the sessionFactory.getCurrentSession() -- the reason I think this might work is that method should create a new session and bind it to the current thread via threadlocal.
您需要为您的服务指定事务上下文。确保您的 Grails 服务是按这种方式完成的。
另一个 Grails 服务链接:
http://www .grails.org/doc/1.0.x/guide/8.%20The%20Service%20Layer.html
You need to specify a transaction context for your service. Make sure your Grails services are done this way.
Another Grails service link:
http://www.grails.org/doc/1.0.x/guide/8.%20The%20Service%20Layer.html