Hibernate Grails2.5.0二级抽象域类创建它';s自己的桌子,即使它不应该';T
如果我创建这样的抽象域类:Hibernate Grails2.5.0二级抽象域类创建它';s自己的桌子,即使它不应该';T,hibernate,grails,inheritance,Hibernate,Grails,Inheritance,如果我创建这样的抽象域类: abstract class DomainBase { LocalDateTime created = LocalDateTime.now() LocalDateTime updated static constraints = { created nullable: false updated nullable: true } static mapping = { tabl
abstract class DomainBase {
LocalDateTime created = LocalDateTime.now()
LocalDateTime updated
static constraints = {
created nullable: false
updated nullable: true
}
static mapping = {
tablePerConcreteClass true
created column: 'CREATED'
updated column: 'UPDATED'
}
def beforeUpdate() {
this.updated = LocalDateTime.now()
}
}
然后我可以用它扩展其他域类,它们将继承所有内容(属性、约束、映射和拦截器),生成的数据库不包含具体的domain\u BASE
表。因此,一切都按预期进行
但是,如果我创建了另一个扩展DomainBase的抽象类,例如:
abstract class EntityBase extends DomainBase {
User createdBy
Boolean active = true
static constraints = {
createdBy nullable: false
active nullable: true
}
static mapping = {
tablePerConcreteClass true
createdBy column: 'CREATED_BY_ID'
active column: 'ACTIVE'
}
}
然后生成的数据库将有一个具体的实体库
表。这就是问题所在
我所能收集到的建议解决方案是让基类是普通POGO的,而不是域对象,但是映射不是继承的,我太懒了,无法将映射复制粘贴到我创建的每个域类中
此外,如果我试图使这些域对象成为traits,我甚至无法运行该应用程序,因为它在编译过程中与NPE断开
有没有一种简单而优雅的方法来解决这个问题?据我所知,Grails2.4.x中的映射是无法继承的,它认为2.5.0中的映射也是一样的
作为一种解决方法,您可以使用和更改域类的脚手架模板。我目前的解决方案(我对此有点满意)是一种仅包装到“实用程序”闭包中的自适应解决方案,如下所示:
/**
* Domain related utilities
*/
class DomainUtil {
private DomainUtil() {}
/**
* Utility for inheriting mapping definitions from non-domain classes (classes defined in src/groovy)<br/>
* Adapted from <a href="https://stackoverflow.com/a/18339655/1182835">https://stackoverflow.com/a/18339655/1182835</a>
* @param source - source class from which to inherit the mappings
* @param destination - closure to which the mappings will be added
*/
static def inheritDomainMappingFrom = { source, destination ->
def copyMapping = source.mapping.clone()
copyMapping.delegate = destination
copyMapping.call()
}
}
以及继承Foo
的域类Bar
:
class Bar extends Foo {
Integer prop3
String prop4
String prop5
static mapping = {
DomainUtil.inheritDomainMappingFrom(Foo, delegate)
prop3 column: 'PROP3'
prop4 column: 'PROP4'
prop5 column: 'PROP5'
}
}
使用DomainUtil.inheritDomainMappingFrom(Foo,delegate)
myBar
domain类将继承Foo
抽象基类中的所有映射定义。对我来说,这是一个充分的折衷方案,因为它更容易编写,也更容易让参与或维护项目的人理解
正如Yannic AT所建议的,这也是一个可能的解决方案,但它包含一些让我感到不快的缺点:
但是,将
@ToString
注释添加到我的所有域类中非常有用。据我所见,在扩展域类时,映射是继承的,而在扩展非域类时,映射只是不继承的。不过我会研究脚手架模板。你读过吗?是的,我读过。但是,我不认为它是一个优雅的解决方案,因此拒绝使用它。你是对的,这不是一个优雅的解决方案,但我与域类继承有类似的问题,这是我发现的唯一解决方案。现在我正在使用脚手架模板,但继承可能会更加优雅。是的,脚手架模板是一个好主意,但只有在从头开始项目时。虽然我想知道。。。映射是一个闭包,对吗?因此,您链接的答案中的代码片段不能被制作成,比方说,“实用程序闭包”并注入到映射闭包中。这很难解释,我会尝试一下,然后用结果编辑OP。
class Bar extends Foo {
Integer prop3
String prop4
String prop5
static mapping = {
DomainUtil.inheritDomainMappingFrom(Foo, delegate)
prop3 column: 'PROP3'
prop4 column: 'PROP4'
prop5 column: 'PROP5'
}
}