将地图和属性列表保留为Grails中的JSON

Joh*_*ann 14 grails persistence json grails-orm

编辑:onload()方法更改为afterLoad():否则对象可能无法正确传递给地图.


我目前正在使用一些具有大量动态,复杂属性的域类,我需要持续定期更新.

我将这些保存在每个类的Map结构中,因为这样可以很容易地在我的控制器等中进行引用.

但是,由于Grails似乎无法在DB中持久保存像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)
  }
}
Run Code Online (Sandbox Code Playgroud)

这很好用,因为我只从数据库加载数据,但是当我想将我的更改保存到数据库时,我遇到了麻烦.例如,当我执行以下操作时

/* 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)
Run Code Online (Sandbox Code Playgroud)

这通常不起作用,因为,我猜(?),GORM将忽略save()请求,因为地图本身是瞬态的,并且在持久化属性中没有发现任何变化.

如果我破解上面的第3步并将其更改为:我可以按预期工作

// 3.Alternative save:
complexMapStructureAsJSON="" //creating a change in persisted property (which will be overwritten anyway by the beforeUpdate closure)
c.save(flush:true)
Run Code Online (Sandbox Code Playgroud)

对我来说,这不是一个非常优雅的处理我的问题.问题:

  1. 是否有更简单的方法来保留我复杂的动态地图数据?
  2. 如果我需要像现在这样做,有没有办法避免步骤3中的黑客入侵?

Ove*_*ous 8

对于第二种情况,则可以使用beforeValidate事件,而不是beforeInsertbeforeUpdate事件,以确保正确的改变传播.

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)
  }
}
Run Code Online (Sandbox Code Playgroud)