我正在使用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]
}
在分配刚刚传递给视图的值后,您可以看到我没有保存。
答案 0 :(得分:1)
Grails使用Open Session In View(OSIV)模式,在Web请求开始时打开Hibernate会话(并存储在本地线程中以便于访问),并在请求结束时只要没有异常,就会刷新并关闭Hibernate会话。在任何刷新期间,Hibernate会查看所有“活动”对象实例,并遍历每个持久属性以查看它是否“脏”。如果是这样,即使您没有明确调用save()
,您的更改也会被推送到数据库。这是可能的,因为当Hibernate从数据库行创建实例时,它会缓存原始数据,以便稍后与可能更改的实例属性进行比较。
很多时候这是有用的行为,但在这样的情况下它会妨碍。虽然有很多修复。其中一个是禁用OSIV,但这通常是一个坏主意,除非你知道你在做什么。在这种情况下,您可以尝试使用两种方法。
一种是将AccTxnMst.get(params.id)
更改为AccTxnMst.read(params.id)
。这不会导致实例严格“只读”,因为您仍然可以显式调用save()
,如果修改了某些内容,则所有实例更改都将保留。但是对于使用read()
检索的实例,没有对原始数据进行缓存,并且在刷新期间没有对这些实例进行脏检查(这是不可能的,因为没有可用于比较的缓存数据)。 p>
在检索不会更新的实例(无论是否进行属性更改)时,通常使用read()
是一个好主意,并使代码更加自我记录。
另一种选择是在控制器操作完成之前在实例上调用discard()
。这将实例与Hibernate会话“分离”,因此当OSIV过滤器在请求结束时运行并刷新Hibernate会话时,您的实例将不会被视为脏,因为Hibernate将无法访问它。
read()
仅对通过id检索的单个实例有意义,而discard()
对任何实例都有用,例如如果它们在映射集合中或由非id查询检索(例如动态查找器,条件查询等)