Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.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
Grails编辑工作在赋值时异常更新数据库_Grails_Gorm_Grails 2.0_Grails Domain Class_Grails Controller - Fatal编程技术网

Grails编辑工作在赋值时异常更新数据库

Grails编辑工作在赋值时异常更新数据库,grails,gorm,grails-2.0,grails-domain-class,grails-controller,Grails,Gorm,Grails 2.0,Grails Domain Class,Grails Controller,我正在使用grails-2.1.1。当我加载编辑页面时,我正在控制器中的编辑操作中分配一些值。但它正在更新我的桌子!虽然我没有存钱。谁能帮我阻止它?下面是我的代码: 我在控制器中的编辑操作>>> def edit() { def accTxnMstInstance = AccTxnMst.get(params.id) if (!accTxnMstInstance) { flash.message = message(code: 'default.not.found

我正在使用grails-2.1.1。当我加载编辑页面时,我正在控制器中的编辑操作中分配一些值。但它正在更新我的桌子!虽然我没有存钱。谁能帮我阻止它?下面是我的代码:

我在控制器中的编辑操作>>>

def edit() {
    def accTxnMstInstance = AccTxnMst.get(params.id)
    if (!accTxnMstInstance) {
        flash.message = message(code: 'default.not.found.message', args: [message(code: 'accTxnMst.label', default: 'AccTxnMst'), params.id])
        redirect(action: "list")
        return
    }

    accTxnMstInstance?.accTxnDtls?.each {
        if (it?.debitCoa != null && it?.debitCoa != "") {
            String debitCoaVal = ""
            List<String> items = Arrays.asList(it?.debitCoa?.split("\\s*~\\s*"))
            items.each {
                List itemList = new ArrayList()
                List<String> subItems = Arrays.asList(it.split("\\^"))
                subItems.each {
                    itemList.add(it)
                }
                itemList.add("false")
                itemList.add("0")

                itemList.each {
                    debitCoaVal += it.toString() + "^"
                }
                debitCoaVal += "~"
            }

            it?.debitCoa = debitCoaVal
            debitCoaVal = ""
        }

        if (it?.creditCoa != null && it?.creditCoa != "") {
            String creditCoaVal = ""
            List<String> items = Arrays.asList(it?.creditCoa?.split("\\s*~\\s*"))
            items.each {
                List itemList = new ArrayList()
                List<String> subItems = Arrays.asList(it.split("\\^"))
                subItems.each {
                    itemList.add(it)
                }
                itemList.add("false")
                itemList.add("0")

                itemList.each {
                    creditCoaVal += it.toString() + "^"
                }
                creditCoaVal += "~"
            }

            it?.creditCoa = creditCoaVal
            creditCoaVal = ""
        }
    }

    [accTxnMstInstance: accTxnMstInstance]
}
def edit(){
def accTxnMstInstance=AccTxnMst.get(参数id)
如果(!accTxnMstInstance){
flash.message=message(代码:“default.not.found.message”,参数:[消息(代码:“accTxnMst.label”,默认值:“accTxnMst”),参数id])
重定向(操作:“列表”)
回来
}
accTxnMstInstance?accTxnDtls?每个{
如果(it?.debitCoa!=null&&it?.debitCoa!=“”){
字符串debitcapal=“”
列表项=数组.asList(it?.debitCoa?.split(“\\s*~\\s*”)
每项{
List itemList=newarraylist()
列表子项=Arrays.asList(it.split(\\^)))
各分项{
itemList.add(它)
}
itemList.add(“false”)
itemList.add(“0”)
itemList.each{
debitcapal+=it.toString()+“^”
}
DebitAval+=“~”
}
it?.debitCoa=debitCoaVal
debitcapal=“”
}
如果(it?.creditCoa!=null&&it?.creditCoa!=“”){
字符串creditCoaVal=“”
列表项=数组.asList(it?.creditCoa?.split(“\\s*~\\s*”)
每项{
List itemList=newarraylist()
列表子项=Arrays.asList(it.split(\\^)))
各分项{
itemList.add(它)
}
itemList.add(“false”)
itemList.add(“0”)
itemList.each{
creditCoaVal+=it.toString()+“^”
}
creditCoaVal+=“~”
}
它?.creditCoa=creditCoaVal
creditCoaVal=“”
}
}
[ACCTXNMSTANCE:ACCTXNMSTANCE]
}

您可以看到,在分配了传递给视图的值之后,我并没有进行保存。

Grails使用视图中的开放会话(OSIV)模式,在web请求开始时打开一个Hibernate会话(并存储在本地线程中以使其易于访问),在请求结束时,只要没有异常,将刷新并关闭休眠会话。在任何刷新过程中,Hibernate都会查看所有“活动”对象实例,并在每个持久性属性中循环,以查看它是否“脏”。如果是这样,即使您没有显式调用
save()
,您的更改也会被推送到数据库中。这是可能的,因为当Hibernate从数据库行创建实例时,它会缓存原始数据,以便稍后与可能更改的实例属性进行比较

很多时候,这是一种有益的行为,但在这种情况下,它会成为阻碍。不过有很多修复方法。一个极端的方法是禁用OSIV,但这通常是一个坏主意,除非你知道自己在做什么。在这种情况下,有两件事你可以尝试,应该工作

一种是将
AccTxnMst.get(params.id)
更改为
AccTxnMst.read(params.id)
。这不会导致实例严格为“只读”,因为您仍然可以显式调用
save()
,如果修改了某些内容,所有实例更改都将被持久化。但是,对于使用
read()
检索的实例,原始数据的缓存并没有完成,并且在刷新这些实例的过程中也没有脏的检查(因为没有缓存的数据可以比较,所以无论如何这是不可能的)

通常,在检索不需要更新的实例(无论是否更改属性)时,使用
read()
是一个好主意,这会使代码更加自我记录

另一个选项是在控制器操作完成之前对实例调用
discard()
。这会将实例与Hibernate会话“分离”,因此当OSIV筛选器在请求结束时运行并刷新Hibernate会话时,您的实例不会被视为脏实例,因为Hibernate无权访问它


read()
仅对通过id检索的单个实例有意义,而
discard()
对任何实例都有用,例如,如果它们位于映射集合中,或者是通过非id查询(例如,动态查找器、条件查询等)检索的。

如果在控制器操作开始时使用@Transactional,则将其删除,然后你可以把它添加到你想要的动作中。所以您无法访问数据库进行一些不需要的操作。我没有在控制器或操作之前使用@Transactional注释。仅供参考,我也尝试过在操作之前使用@Transactional(readOnly=true),但运气不佳。将autoFlush设置为false是另一个可能会产生意外效果的选项,只有在您知道自己在做什么的情况下才应该更改。一般来说,自动刷新是一件好事,但在这种不需要自动刷新的情况下,我更喜欢显式地处理事情,但在其他情况下保留默认行为。