3

在 Grails 中使用抽象(或非抽象)继承时,以下内容对我不起作用。

很快,我的继承如下:

abstract BaseClass               { ... }
SomeClass      extends BaseClass { ... }
SomeOtherClass extends BaseClass { ... }

然后在另一个域对象中:

ThirdClass {
    ...
    BaseClass baseProperty
    ...
}

但是现在,当我尝试将该属性设置为 aSomeClassSomeOtherClass实例时,Grails 会出现:

错误 util.JDBCExceptionReporter - 无法添加或更新子行:外键约束失败...

这不可能吗?


我也尝试过让基类不是抽象的,并尝试将SomeClassorSomeOtherClass实例转换为BaseClass. 它们产生相同的错误。


更新

我刚检查过。它适用于我添加的第一个子类。但是,一旦我尝试添加另一个子类,它就会失败。

换句话说:

def prop1 = new ThirdClass(baseProperty: instanceOfSomeClass).save()

工作正常。但是当我尝试去做时:

def prop2 = new ThridClass(baseProperty: instanceOfSomeOtherClass).save()

它失败。


更新 2

进一步调查表明,在表创建过程中出现了问题。它正确地将两个外键添加到ThirdClass表中,但键错误地引用:

CONSTRAINT `...` FOREIGN KEY (`some_id`) REFERENCES `base_class` (`id`),
CONSTRAINT `...` FOREIGN KEY (`some_id`) REFERENCES `some_class` (`id`)

不知道为什么选择基类和子类之一?我试过清洁等。

4

2 回答 2

7

首先,在域结构之外创建您的 BaseClass。它必须是一个外部类,放在脚本文件夹,源文件夹。

package com.example.model

/**
 * @author Inocencio
 */
class BaseClass {

    Date createdAt = new Date()

}

现在,创建一个常规域类并扩展它。

package com.example.domain

import com.example.model.BaseClass

class SomeClass extends BaseClass {

    String name

    static constraints = {
        name(nullable: false)
    }

}

正如你所看到的,一旦你坚持 SomeClass 一个 createdAt 字段也被填充和保存。检查测试类:

@TestFor(SomeClass)
class SomeClassTests {

    void testSomething() {
        def some = new SomeClass()
        some.name = "Hello There"
        some.save()

        //find it
        def someFind = SomeClass.list()[0]

        assert someFind

        assertTrue someFind.createdAt != null

//        println "Date: $someFind.createdAt"
//        println "Name: $someFind.name"
    }
}

我希望它会有所帮助。

于 2012-09-11T12:32:12.397 回答
0

我刚刚创建了你的类结构(Grails 2.1.0),没有问题。它在模拟和单元测试时有效。从表单中保存脚手架和 SomeClass 和 ThirdClass 实例时也是如此。尝试清理你的数据库,特别是如果你没有使用“create-drop”模式。也许还有一些旧的约束。最后一件事,您没有指定错误发生的时间 - 在保存(创建或更新)时?不太可能在属性集上获得 JDBC 异常,是吗?我不记得了,但可能默认情况下简单属性没有级联,然后在保存 ThirdClass 实例之前尝试保存 SomeClass 实例。您也可以使用 hasOne 关系自动级联而不是声明简单属性,例如:

class ThirdClass {
    ...
    static hasOne = [baseProperty:BaseClass]
}
于 2012-09-11T12:06:24.537 回答