存储 Map<K,V> 的 Grails 域对象
Grails domain object storing Map<K,V>
我从 Grails/GORM 文档中了解到,如果您希望存储对象的 Map,键和值都需要是字符串:Map<String,String>
.
我想使用另一个域对象 (Animal
) 作为此映射中的键,但由于上述限制,这是不可能的。 Animal
的标识符可以很容易地转换为字符串类型,但如果我这样做,我认为 GORM 不会聪明到在检索父对象时执行映射。
有人 运行 喜欢这个吗?
我认为这应该可行:
假设您的域class有一个地图:
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()}"
现在这将查找域 class 方法并根据调用尝试 return 动物对象
在启动之前,我需要添加 1 只动物和 1 只猴子,因为它会获取或执行上面的查找或第一个对象。所以在我的 bootstrap:
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
还有一些 class 字符串错误,不确定是哪个位引起的 - 输出中的 println 看起来如您所愿。
您可能必须选择不同的方法来保存密钥并使用 Animal 作为主要的 class 来查询所以一些其他代码的密钥然后您可以将 findByAnimal 更改为始终 return 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
}
由于 Animal
或 Monkey
扩展了 Animal,因此更高的调用发生了变化。上例中缺少两个 classes:
package test
class Animal {
String name
}
package test
class Monkey extends Animal {
}
我从 Grails/GORM 文档中了解到,如果您希望存储对象的 Map,键和值都需要是字符串:Map<String,String>
.
我想使用另一个域对象 (Animal
) 作为此映射中的键,但由于上述限制,这是不可能的。 Animal
的标识符可以很容易地转换为字符串类型,但如果我这样做,我认为 GORM 不会聪明到在检索父对象时执行映射。
有人 运行 喜欢这个吗?
我认为这应该可行:
假设您的域class有一个地图:
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()}"
现在这将查找域 class 方法并根据调用尝试 return 动物对象
在启动之前,我需要添加 1 只动物和 1 只猴子,因为它会获取或执行上面的查找或第一个对象。所以在我的 bootstrap:
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
还有一些 class 字符串错误,不确定是哪个位引起的 - 输出中的 println 看起来如您所愿。
您可能必须选择不同的方法来保存密钥并使用 Animal 作为主要的 class 来查询所以一些其他代码的密钥然后您可以将 findByAnimal 更改为始终 return 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
}
由于 Animal
或 Monkey
扩展了 Animal,因此更高的调用发生了变化。上例中缺少两个 classes:
package test
class Animal {
String name
}
package test
class Monkey extends Animal {
}