在 Grails 中将映射和属性列表持久保存为 JSON
编辑:onload() 方法更改为 afterLoad():否则对象可能无法正确传递到地图。
我目前正在使用一些具有大量动态、复杂属性的域类,我需要保留并定期更新它们。
我将它们保存在每个类的 Map 结构中,因为这使得在我的控制器等中引用变得容易。
但是,由于 Grails 似乎无法在数据库中保留复杂的属性类型,如 List 和 Map,我正在使用以下方法通过 JSON String 对象实现此目的:
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)
}
}
只要我只从数据库加载数据,这种方法就很有效,但是当我想将更改保存回数据库时,我会遇到麻烦。例如,当我执行以下操作时
/* 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)
,这通常不起作用,因为我猜(?),GORM 将忽略 save() 请求,因为地图本身是暂时的,并且在持久属性中没有发现任何更改。
我可以使其按预期工作
// 3.Alternative save:
complexMapStructureAsJSON="" //creating a change in persisted property (which will be overwritten anyway by the beforeUpdate closure)
c.save(flush:true)
如果我修改上面的步骤 3 并将其更改为:对我来说,这不是对我的问题的非常优雅的处理, 。 问题:
- 是否有更简单的方法来保存复杂的动态地图数据?
- 如果我需要按照目前的方式进行操作,有没有办法避免步骤 3 中的 hack ?
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 ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对于选项 2,您可以使用
beforeValidate
事件而不是beforeInsert
和beforeUpdate
事件,以确保更改正确传播。For option 2, you can use the
beforeValidate
event instead ofbeforeInsert
andbeforeUpdate
events to ensure that the change propagates correctly.当然,我对您正在构建的应用程序了解不多,但查找替代数据存储模型(尤其是 NOSQL 数据库)不会有什么坏处。 Grails 也得到了一些支持。
I of course do not know much about the application you are building, but it won't hurt to look up alternate data storage models particularly NOSQL databases. Grails has got some support for them too.
Grails 可以开箱即用地持久化 List 和 Map,您不需要编写复杂的转换代码和滥用 Json。
地图示例:
列表示例:
我认为这是处理它的更简单、更清晰的方式。
Grails can persist List and Map out of the box, you don't need to write complex conversion code and abuse Json.
Example for Map:
Example for List:
I think this is much easier and cleaner way how to deal with it.
回应
Grails 可以将集合、列表和映射持久保存到数据库 。这可能是比处理 JSON 转换更简单的方法。要将地图持久保存到数据库中,您需要将其包含在 hasMany 属性中。
文档表明使用 Bag 可能会更有效。
In response to
Grails can persist Sets, Lists and Maps to the database. That may be a simpler approach than dealing with JSON conversions. To have the map persisted to the database you need to include it in the hasMany property.
The documentation suggests that using a Bag may be more efficient.