有没有办法在grails中创建与任意域对象的关系
Is there a way to create a relationship to an arbitraray domain object in grails
有没有办法在 grails 中创建与任意域对象的关联?
类似
class ThingHolder {
DomainObject thing;
}
然后
Book b=new Book(title: "Grails 101").save()
Author a=new Author(name: "Abe").save()
ThingHolder t1=new ThingHolder(thing:b).save()
ThingHolder t2=new ThingHolder(thing: a).save()
所以
ThingHolder.get(t1.id).thing // will be a Book
和
ThingHolder.get(t2.id).thing // will be an Author.
更新(基于评论)
由于您不想(或不能)在您的域模型中扩展另一个 class,因此使用 GORM 是不可能的。
原始答案
是的,你可以做到。这叫做继承。在您的情况下,您将有一个 Thing
,它是 Author
和 Book
的超级 class。
您的域模型可能如下所示:
class Thing {
// anything that is common among things should be here
}
class Author extends Thing {
// anything that is specific about an author should be here
}
class Book extends Thing {
// anything that is specific about a book should be here
}
class ThingHolder {
Thing thing
}
由于 Author
和 Book
都扩展了 Thing
,因此它们也被认为是 Thing
。
但是,在不了解继承以及 Grails/GORM 如何对数据库中的数据建模的情况下这样做是短视的。您应该充分研究这些主题,以确保这确实是您想要的。
我仍在寻找更简单的方法来执行此操作,但这似乎可以完成工作。
class ThingHolder {
static constraints = {
thing bindable:true // required so 'thing' is bindable in default map constructor.
}
def grailsApplication;
Object thing;
String thingType;
String thingId;
void setThing(Object thing) { //TODO: change Object to an interface
this.thing=thing;
this.thingType=thing.getClass().name
this.thingId=thing.id; //TODO: Grailsy way to get the id
}
def afterLoad() {
def clazz=grailsApplication.getDomainClass(thingType).clazz
thing=clazz.get(thingId);
}
}
假设您有书籍和作者(不会覆盖域对象的 ID 属性)。
def thing1=new Author(name : "author").save(failOnError:true);
def thing2=new Book(title: "Some book").save(failOnError:true);
new ThingHolder(thing:thing1).save(failOnError:true)
new ThingHolder(thing:thing2).save(failOnError:true)
ThingHolder.list()*.thing.each { println it.thing }
我在这两个答案中发现了一些非常有用的提示。
How to make binding work in default constructor with transient values.
How to generate a domain object by string representation of class name
有没有办法在 grails 中创建与任意域对象的关联?
类似
class ThingHolder {
DomainObject thing;
}
然后
Book b=new Book(title: "Grails 101").save()
Author a=new Author(name: "Abe").save()
ThingHolder t1=new ThingHolder(thing:b).save()
ThingHolder t2=new ThingHolder(thing: a).save()
所以
ThingHolder.get(t1.id).thing // will be a Book
和
ThingHolder.get(t2.id).thing // will be an Author.
更新(基于评论)
由于您不想(或不能)在您的域模型中扩展另一个 class,因此使用 GORM 是不可能的。
原始答案
是的,你可以做到。这叫做继承。在您的情况下,您将有一个 Thing
,它是 Author
和 Book
的超级 class。
您的域模型可能如下所示:
class Thing {
// anything that is common among things should be here
}
class Author extends Thing {
// anything that is specific about an author should be here
}
class Book extends Thing {
// anything that is specific about a book should be here
}
class ThingHolder {
Thing thing
}
由于 Author
和 Book
都扩展了 Thing
,因此它们也被认为是 Thing
。
但是,在不了解继承以及 Grails/GORM 如何对数据库中的数据建模的情况下这样做是短视的。您应该充分研究这些主题,以确保这确实是您想要的。
我仍在寻找更简单的方法来执行此操作,但这似乎可以完成工作。
class ThingHolder {
static constraints = {
thing bindable:true // required so 'thing' is bindable in default map constructor.
}
def grailsApplication;
Object thing;
String thingType;
String thingId;
void setThing(Object thing) { //TODO: change Object to an interface
this.thing=thing;
this.thingType=thing.getClass().name
this.thingId=thing.id; //TODO: Grailsy way to get the id
}
def afterLoad() {
def clazz=grailsApplication.getDomainClass(thingType).clazz
thing=clazz.get(thingId);
}
}
假设您有书籍和作者(不会覆盖域对象的 ID 属性)。
def thing1=new Author(name : "author").save(failOnError:true);
def thing2=new Book(title: "Some book").save(failOnError:true);
new ThingHolder(thing:thing1).save(failOnError:true)
new ThingHolder(thing:thing2).save(failOnError:true)
ThingHolder.list()*.thing.each { println it.thing }
我在这两个答案中发现了一些非常有用的提示。
How to make binding work in default constructor with transient values.
How to generate a domain object by string representation of class name