Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate Grails2.5.0二级抽象域类创建它';s自己的桌子,即使它不应该';T_Hibernate_Grails_Inheritance - Fatal编程技术网

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)
my
Bar
domain类将继承
Foo
抽象基类中的所有映射定义。对我来说,这是一个充分的折衷方案,因为它更容易编写,也更容易让参与或维护项目的人理解

正如Yannic AT所建议的,这也是一个可能的解决方案,但它包含一些让我感到不快的缺点:

  • 它对重构不友好——如果在已经完成大量开发之后需要添加某些属性/约束/映射/拦截器,那么所有更改都需要追溯添加到所有现有类中
  • 不遵循DRY原则-通过修改模板,我们所做的只是指示grails域生成器将新添加的代码复制并粘贴到我们创建的每个新域类中。因此,如果我们有很多域类,我们将有很多重复的代码,这反过来会使重构成为一场噩梦(见1)
  • 只有当我们希望将某些属性添加到所有域类中时,它才起作用,否则我们必须删除生成的代码,在我看来,这违背了模板的目的

  • 但是,将
    @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'
        }
    }