3

对于我目前正在处理的项目,我需要将属性动态添加到域类并稍后将它们保存在数据库中。一般来说,我需要一个附加到“普通”域类的键/值存储。遗憾的是我不能使用 NoSQL 数据库(例如 Redis)。

我的方法是通过在 asave()中识别它们afterInsertafterUpdate将它们写入另一个表来处理 a 上的附加属性 - 我不希望在域类中使用 map 属性,而是使用附加的“字段”表(以更好地支持搜索)。

我尝试使用metaClass 方法添加属性:

person.metaClass.middlename = "Biterius"
assert person.middlename == "Biterius"    // OK

这行得通,我可以识别 afterInsert/afterUpdate 方法中的其他属性,但似乎此后我无法更改该值 - 即,以下内容不起作用:

person.middlename = "Tiberius"
assert person.middlename == "Tiberius"    // FAIL

然后我尝试了一种Expando 方法,通过 Expando 类(直接(“Person extends Expando”)和通过抽象中间类(“Person extends AbstractPerson”和“AbstractPerson extends Expando”))扩展 Person 类。

def person = new Person()
assert person in Person          // OK
assert person in AbstractPerson  // OK
assert person in Expando         // OK

两种变体都不起作用-我可以将值分配给任意“属性”,但未存储值!

person.mynewproperty = "Tiberius"  // no MissingPropertyException is thrown 
println person.mynewproperty       // returns null

那么如何在运行时以编程方式将属性添加到域类,在 afterInsert 或 afterUpdate 期间更改它们并检索它们,以便“手动”将它们存储在“字段”表中?

还是我做错了什么?还有其他/更简单的方法可以做到这一点吗?

4

2 回答 2

0

将您的数据库变成“NoSQL”怎么样?

在我的一个项目中,我只是使用字符串属性将地图存储为 JSON 对象。对于 Groovy 来说,在 map 和 JSON-Object 之间进行转换并不是什么大问题。而且由于您可以像访问具有属性的对象一样访问地图,因此我发现此解决方案非常方便。

唯一的缺点:您必须提前计划字符串属性的大小......

更新:对不起,刚刚读到你想支持搜索......

关于什么

class Person {
  ...
  static hasMany = [extProperties:KeyValue]
  ...
  def invokeMethod(String name, args) {
    if (name.startsWith('get')) {
       //an unknown properties's getter is called
    }
    //add same for setter
  }
}


class KeyValue {
  String key
  String value
}

我想这样的模式会给你你需要的所有自由。即使没有hasMany,您也可以使用invokeMethod来处理您的外部表...

getter 和 setter 可以将您的值保存在瞬态字符串属性 ( static transients = ['myTransientProperty']) 中。这个属性应该在afterInsert/ `afterUpdate` 事件中可用。

于 2012-09-21T18:15:54.987 回答
0

你为什么不在域对象上创建一个字符串映射并手动存储你的额外数据呢?除非您要存储复杂的数据,否则您应该能够将所需的任何内容转换为字符串。

于 2012-09-21T18:48:41.260 回答