Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate 圣杯。将更新保存到会话作用域中的对象不起作用。懒散初始化异常_Hibernate_Grails_Gorm - Fatal编程技术网

Hibernate 圣杯。将更新保存到会话作用域中的对象不起作用。懒散初始化异常

Hibernate 圣杯。将更新保存到会话作用域中的对象不起作用。懒散初始化异常,hibernate,grails,gorm,Hibernate,Grails,Gorm,我有一个简单的用例,它不起作用 resume操作从数据库获取一个对象,将其存储在会话范围中,然后呈现一个视图,该视图显示一个可以更改对象字段的表单。save处理表单提交,并需要保存更新的对象。域对象由基本字段和复杂字段组成。这个问题与grails会话作用域hibernate persistence session有关,这在其他线程中已经讨论过,但它似乎不起作用。阅读文档和其他讨论,我似乎应该使用attach(),但它不起作用,导致下面出现懒散初始化异常。如果我不执行merge(),我会得到相同的

我有一个简单的用例,它不起作用

resume
操作从数据库获取一个对象,将其存储在会话范围中,然后呈现一个视图,该视图显示一个可以更改对象字段的表单。save处理表单提交,并需要保存更新的对象。域对象由基本字段和复杂字段组成。这个问题与grails会话作用域hibernate persistence session有关,这在其他线程中已经讨论过,但它似乎不起作用。阅读文档和其他讨论,我似乎应该使用
attach()
,但它不起作用,导致下面出现
懒散初始化
异常。如果我不执行
merge()
,我会得到相同的异常:

could not initialize proxy - no Session. Stacktrace follows:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at com.toxservices.ApplicationController$_saveRequestForService_closure1$$EOB7zOh6.doCall(ApplicationController.groovy:302)
    at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:573)
使用
merge()
不会导致异常,但似乎不起作用,因为对象的值在数据库中没有更新。我可以看到表单提交时更新的值,保存方法没有出错,但是值没有更新

我做错了什么?这似乎是一个非常典型的用例,因此非常令人费解。下面是示例代码。我擦洗它,只留下相关的碎片

def resume(){
    def rfs = Rfs.get(params.id)
    session.rfs = rfs
    render(view: "index", model: [rfs:rfs]) 
}
//index presents a form where Rfs can be updated and form re-submitted

def save() {
    def rfs
    if(session.rfs){
        rfs = session.rfs
        captureFormData(rfs, params)
        saveRfs(rfs, true)
    }
}

private def saveRfs(rfs, merge) {
//      if(!rfs.isAttached()){
//          rfs.attach()
//      }

    if(merge){
        rfs = rfs.merge()
    }

    Rfs.withTransaction {

        rfs.product.hAddress.address.save()
        rfs.product.mAddress.address.save()
        rfs.product.sContact.address.save()
        rfs.product.tContact.address.save()
        rfs.product.mContact.address.save()

        rfs.product.hAddress.save()
        rfs.product.mAddress.save()
        rfs.product.sContact.save()
        rfs.product.tontact.save()
        rfs.product.mContact.save()

        rfs.product.X.save()
        rfs.product.save()  
        ...
        rfs.save()
    }   
}

你的方法看起来很不传统。无论如何,您是否可以尝试将
attach()
的逻辑移动到
withTransaction
块中,并注释掉
merge()
逻辑。如果第一种方法失败,请尝试将
withTransaction
块移动到
save()
中,将
If
块包装起来。虽然,有一种更好的方法可以在控制器中写入逻辑。你为什么不从视图(通过表单隐藏字段)将Rfs.id提交回save(),并再次使用Rfs.get()而不是在会话中保存Rfs?LOL.@user2264997刚刚提到了你我的更好方法…:)谢谢你们两位。user226*推荐的方法有效。我不知道为什么我没有想到它。也许是出于习惯,跨多个请求携带状态通常是通过会话作用域完成的,所以我开始这样做。在保存过程中必须再次按id查询对象感觉很奇怪,因为在我的
resume
操作开始时已经有了它。它确实有效,所以我很高兴@dmahapatro在withTransaction块中放置attach时未执行此操作。我仍然对最初的工作方法感到好奇,因为它只是觉得应该工作,尽管它不那么紧迫。