Grails 编辑在赋值时异常更新数据库
Grails edit working abnormally updating database on value assign
我正在使用 grails-2.1.1。当我加载编辑页面时,我在控制器的编辑操作中分配了一些值。但它正在更新我的 table!虽然我没有储蓄。我该如何阻止它?
下面是我的代码。我在控制器中的编辑操作:
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]
}
你可以看到我在给view赋值后并没有保存
Grails 使用 Open Session In View (OSIV) 模式,在 Web 请求开始时会打开一个 Hibernate 会话(并存储在本地线程中以使其易于访问)并在请求结束时只要没有异常请求,Hibernate 会话就会刷新并关闭。在任何刷新期间,Hibernate 查看所有 "active" 对象实例并循环遍历每个持久性 属性 以查看它是否是 "dirty"。如果是这样,即使您没有显式调用 save()
,您的更改也会被推送到数据库中。这是可能的,因为当 Hibernate 从数据库行创建实例时,它会缓存原始数据以便稍后与可能更改的实例属性进行比较。
很多时候这是有帮助的行为,但在这种情况下它会成为阻碍。虽然有很多修复。一个极端的做法是禁用 OSIV,但这通常不是一个好主意,除非您知道自己在做什么。在这种情况下,您可以尝试两种应该有效的方法。
一是将AccTxnMst.get(params.id)
改为AccTxnMst.read(params.id)
。这不会导致实例严格 "read-only" 因为您仍然可以显式调用 save()
并且如果修改了某些内容,所有实例更改都将保留。但是对于使用 read()
检索的实例,原始数据的缓存没有完成,并且在刷新这些实例期间没有脏检查(无论如何这是不可能的,因为没有缓存数据可以比较)。
在检索不会更新的实例(无论是否进行 属性 更改)时,使用 read()
通常是一个好主意,并使代码更加自文档化。
另一种选择是在控制器操作完成之前在实例上调用 discard()
。 "detaches" 来自 Hibernate 会话的实例,因此当 OSIV 过滤器在请求结束时运行并刷新 Hibernate 会话时,您的实例不会被视为脏的,因为 Hibernate 无法访问它。
read()
仅对通过 id 检索的单个实例有意义,而 discard()
对任何实例都有用,例如如果它们在映射集合中或由非 ID 查询检索(例如动态查找器、条件查询等)
我正在使用 grails-2.1.1。当我加载编辑页面时,我在控制器的编辑操作中分配了一些值。但它正在更新我的 table!虽然我没有储蓄。我该如何阻止它?
下面是我的代码。我在控制器中的编辑操作:
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]
}
你可以看到我在给view赋值后并没有保存
Grails 使用 Open Session In View (OSIV) 模式,在 Web 请求开始时会打开一个 Hibernate 会话(并存储在本地线程中以使其易于访问)并在请求结束时只要没有异常请求,Hibernate 会话就会刷新并关闭。在任何刷新期间,Hibernate 查看所有 "active" 对象实例并循环遍历每个持久性 属性 以查看它是否是 "dirty"。如果是这样,即使您没有显式调用 save()
,您的更改也会被推送到数据库中。这是可能的,因为当 Hibernate 从数据库行创建实例时,它会缓存原始数据以便稍后与可能更改的实例属性进行比较。
很多时候这是有帮助的行为,但在这种情况下它会成为阻碍。虽然有很多修复。一个极端的做法是禁用 OSIV,但这通常不是一个好主意,除非您知道自己在做什么。在这种情况下,您可以尝试两种应该有效的方法。
一是将AccTxnMst.get(params.id)
改为AccTxnMst.read(params.id)
。这不会导致实例严格 "read-only" 因为您仍然可以显式调用 save()
并且如果修改了某些内容,所有实例更改都将保留。但是对于使用 read()
检索的实例,原始数据的缓存没有完成,并且在刷新这些实例期间没有脏检查(无论如何这是不可能的,因为没有缓存数据可以比较)。
在检索不会更新的实例(无论是否进行 属性 更改)时,使用 read()
通常是一个好主意,并使代码更加自文档化。
另一种选择是在控制器操作完成之前在实例上调用 discard()
。 "detaches" 来自 Hibernate 会话的实例,因此当 OSIV 过滤器在请求结束时运行并刷新 Hibernate 会话时,您的实例不会被视为脏的,因为 Hibernate 无法访问它。
read()
仅对通过 id 检索的单个实例有意义,而 discard()
对任何实例都有用,例如如果它们在映射集合中或由非 ID 查询检索(例如动态查找器、条件查询等)