问题描述
编辑:onload()方法更改为afterLoad():否则对象可能无法正确传递到地图。我目前正在使用一些具有许多动态,复杂属性的域类,我需要定期保存和更新。
我将这些保存在Map结构中每个类,因为这使得它很容易引用我的控制器等。
然而,由于Grails似乎不能够持久复杂的属性类型,如列表和地图在数据库我正在使用以下方法通过JSON字符串对象实现此目的:
class ClassWithComplexProperties {
映射complexMapStructure //未持久
字符串complexMapStructureAsJSON //通过onload,beforeInsert,beforeUpdate更新和同步映射
静态瞬变= ['complexMapStructure']
def afterLoad(){//之前(错误!):def onLoad(){
complexMapStructure = JSON。解析(complexMapStructureAsJSON)
}
def beforeInsert(){
complexMapStructureAsJSON = complexMapStructure as JSON
}
def beforeUpdate(){
complexMapStructureAsJSON = complexMapStructure as JSON
}
static constraints = {
complexMapStructureAsJSON(maxSize:20000)
}
}
只要我只从数据库加载数据,这种方式就行得通,但当我想要将更改保存到数据库时遇到麻烦。例如。当我执行以下操作时:
/ * 1.加载json字符串,例如complexMapStructureAsJSON ={
data1:[[1,2],[3,4]],//嵌套整数列表的复杂结构
data1:[[5,6]] //另一个
}:
* /
ClassWithComplexProperties c = ClassWithComplexProperties.get(1)
// 2.更改地图深处的值:
c.complexMapStructure.data1 [0] [0] = 7
// 3.尝试保存:
c.save(flush:true)
这通常不起作用,因为我猜(?),GORM会忽略save()请求由于地图本身是暂时的,并且在持久属性中没有找到变化。
如果我侵入上述步骤3并将其更改为:
// 3.另存为:
complexMapStructureAsJSON =//在持久属性中创建一个更改(它将被beforeUpdate闭包覆盖)
c.save(flush :true)
对我来说,这不是一个非常优雅的处理我的问题。
问题:
- 是否有更简单的方法来保存我的复杂动态地图数据?
- 如果我需要按照我目前的方式执行此操作,是否有办法避免步骤3中的黑客行为?
对于选项2,您可以使用事件而不是 beforeInsert
和 beforeUpdate
事件,以确保更改正确传播。
class ClassWithComplexProperties {
地图complexMapStructure //未持久
字符串complexMapStructureAsJSON //通过onload更新并与map同步, beforeInsert,beforeUpdate
static transients = ['complexMapStructure']
$ b $ def onLoad(){
complexMapStructure = JSON.parse(complexMapStructureAsJSON)
//>>>>>>>>>>>>>>>>>>>
def beforeValidate(){
complexMapStructureAsJSON = complexMapStructure as JSON
}
//>>>>>>>>>>>>>>>>>> ;>>>
static constraints = {
complexMapStructureAsJSON(maxSize:20000)
}
}
EDIT: onload() method changed to afterLoad(): Otherwise objects might not be passed properly to the map.
I am currently using some domain classes with a lot of dynamic, complex properties, that I need to persist and update regularly.
I keep these in a Map structure for each class since this makes it easy for referencing in my controllers etc.
However, since Grails does not seem to be able to persist complex property types like List and Map in the DB I am using the following approach to achieve this via JSON String objects:
class ClassWithComplexProperties {
Map complexMapStructure //not persisted
String complexMapStructureAsJSON //updated and synched with map via onload,beforeInsert,beforeUpdate
static transients = ['complexMapStructure']
def afterLoad() { //was previously (wrong!): def onLoad() {
complexMapStructure=JSON.parse(complexMapStructureAsJSON)
}
def beforeInsert() {
complexMapStructureAsJSON= complexMapStructure as JSON
}
def beforeUpdate() {
complexMapStructureAsJSON= complexMapStructure as JSON
}
static constraints = {
complexMapStructureAsJSON( maxSize:20000)
}
}
This works well as long I am only loading data from the DB, but I run into trouble when I want to save back my changes to the DB. E.g. when I do the following
/* 1. Load the json String, e.g. complexMapStructureAsJSON="""{
data1:[[1,2],[3,4]],//A complex structure of nested integer lists
data1:[[5,6]] //Another one
}""" :
*/
ClassWithComplexProperties c=ClassWithComplexProperties.get(1)
// 2. Change a value deep in the map:
c.complexMapStructure.data1[0][0]=7
// 3. Try to save:
c.save(flush:true)
This will usually not work, since, I guess(?), GORM will ignore the save() request due to the fact that the map itself is transient, and no changes are found in the persisted properties.
I can make it work as intended if I hack step 3 above and change it to:
// 3.Alternative save:
complexMapStructureAsJSON="" //creating a change in persisted property (which will be overwritten anyway by the beforeUpdate closure)
c.save(flush:true)
To me this is not a very elegant handling of my problem.The questions:
- Is there a simpler approach to persist my complex, dynamic map data?
- If I need to do it the way I currently do, is there a way to avoid the hack in step 3 ?
For option 2, you can use the beforeValidate
event instead of beforeInsert
and beforeUpdate
events to ensure that the change propagates correctly.
class ClassWithComplexProperties {
Map complexMapStructure //not persisted
String complexMapStructureAsJSON //updated and synched with map via onload,beforeInsert,beforeUpdate
static transients = ['complexMapStructure']
def onLoad() {
complexMapStructure=JSON.parse(complexMapStructureAsJSON)
}
// >>>>>>>>>>>>>>
def beforeValidate() {
complexMapStructureAsJSON= complexMapStructure as JSON
}
// >>>>>>>>>>>>>>
static constraints = {
complexMapStructureAsJSON( maxSize:20000)
}
}
这篇关于在Grails中将地图和属性列表保存为JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!