存储Map <k,v>的Grails域对象

时间:2017-01-05 16:39:12

标签: grails gorm

我从Grails / GORM文档中了解到,如果您希望存储对象Map,则键和值都需要为字符串:Map<String,String>

我想使用另一个域对象(Animal)作为此映射中的键,但由于上述约束,这是不可能的。 Animal的标识符可以很容易地转换为字符串类型,但如果我这样做,我不相信GORM在检索父对象时会非常聪明地执行映射。

有没有人碰到这个?

1 个答案:

答案 0 :(得分:1)

我认为这应该有效:

假设您有一个包含地图的域类:

class Test {
   String name
   Map myAnimals=[:]

  //When given a specific key it will return actual animal object
  def findAnimal(String myKey) {
    return myAnimals.find{it.key==myKey}?.value
    //What above is doing can be seen broken down here:
    //def ani = myAnimals.find{it.key==myKey}
    //println "ANI::: ${ani} ${ani.value}"
    //def animal = ani?.value
    //return animal

  }
}

保存到地图时的服务

class TestService {
    def save(values) {
    Test test1 = new Test()
    test1.name='something'
    // so to add 3 of animal objects above values would be
    def animal1=Animal.find()
    String key1='ANI'  //For animals 
    def animal2=Monkey.find()  // where Monkey extends Animal (hence the keys)
    String key2='MON'  //For monkeys only
    test1.myAnimals[key1]=animal1
    test1.myAnimals[key2]=animal2
    test1.save()

      /**
      * When you have a real values map that contains useful method you can
      * do it this way - left commented out FYI on manual process above
      Test test = new Test()
      // you now have some map of values coming in that contains a key 
      // and actual object so you could make this up if you are testing
     values.animals?.each{k,v->
                test.myAnimals[k]=v
            }
    }    
    test.save()
    */        
 }

因此,第一个示例values.each是您构建自己的地图的地方,其中包含要保存的密钥和实际域对象。

第二个test1示例是我手动完成的,没有自动值作为测试传递,也可能是最好的起点。

然后当你有测试对象来获取真正的动物(因为你可以看到限制)关键所以一只动物一只猴子一只鸟等等

当你有

Test test = Test.findByName('something)
def animal = test.findAnimal('ANI')
def monkey = test.findAnimal('MON')
println "animal is ${animal} ${animal.getClass()} monkey is ${monkey} ${monkey.getClass()}"

现在将查找域类方法并尝试按照调用返回动物对象

在启动之前,我需要添加1只动物和1只猴子,因为它上面找到或者找到了第一个物体。所以在我的引导程序中:

import test.Animal
import test.Monkey

class BootStrap {

    def init = { servletContext ->

        Animal animal = new Animal()
        animal.name='Daffy Duck'
        animal.save(flush:true)
        Monkey monkey = new Monkey()
        monkey.name='King Kong'
        monkey.save(flush:true)
    }
    def destroy = {
    }
}

当我运行它时,我从println

开始
animal is class test.Animal class java.lang.Class monkey is class test.Monkey class java.lang.Class

另外一些类到字符串错误不确定哪个位导致它 - 输出中的println看起来像你想要的那样。

您可能必须选择不同的方法来保存密钥并使用Animal作为主要类来查询,因此您可以将findByAnimal更改为始终返回Animal对象:

//When given a specific key it will return actual animal object
    Animal findAnimal(String myKey) {
      Animal animal = myAnimals.find{it.key==myKey}?.value
      return animal
    }

由于AnimalMonkey扩展了动物,因此更高的通话被更改了。以上示例中有两个缺少的类:

package test

class Animal {
    String name

}
package test

class Monkey extends Animal {


}