简体   繁体   English

Grails 2抽象域继承问题

[英]Grails 2 abstract domain inheritance issue

The following is not working for me when using abstract (or non-abstract for that matter) inheritance in Grails. 在Grails中使用抽象(或非抽象)继承时,以下内容对我不起作用。

Very quickly, my inheritance is as follows: 很快,我的继承如下:

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

And then in another domain object: 然后在另一个域对象中:

ThirdClass {
    ...
    BaseClass baseProperty
    ...
}

But now, when I try to set that property to either a SomeClass or SomeOtherClass instance, Grails compains: 但是现在,当我尝试将该属性设置为SomeClassSomeOtherClass实例时,Grails会:

ERROR util.JDBCExceptionReporter - Cannot add or update a child row: a foreign key constraint fails ... 错误util.JDBCExceptionReporter - 无法添加或更新子行:外键约束失败...

Is this not possible? 这不可能吗?


I have also tried having the base class not be abstract, and also tried casting the SomeClass or SomeOtherClass instances to BaseClass . 我也试过让基类不是抽象的,并尝试将SomeClassSomeOtherClass实例强制转换为BaseClass They generate the same error. 它们会产生相同的错误。


UPDATE UPDATE

I just checked. 我刚刚检查过 It works for the first sub-class that I add. 它适用于我添加的第一个子类。 But as soon as I try to add the other sub-class it fails. 但是一旦我尝试添加其他子类就失败了。

In other words: 换一种说法:

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

works fine. 工作良好。 But when I then try and do: 但是当我尝试做的时候:

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

it fails. 它失败。


UPDATE 2 更新2

Further investigation shows that something goes wrong during the table creation process. 进一步的调查显示在表创建过程中出现了问题。 It correctly adds two foreign keys to the ThirdClass table, but the keys incorrectly references: 它正确地向ThirdClass表添加了两个外键,但键错误地引用了:

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

Don't know why it's choosing the base class and one of the sub-classes? 不知道为什么选择基类和其中一个子类? I have tried cleaning etc. 我试过清洁等

First of all, create your BaseClass outside domain structure. 首先, 域外结构中创建BaseClass。 It must be an external class, put it on script folder, source folder. 它必须是一个外部类,把它放在脚本文件夹,源文件夹中。

package com.example.model

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

    Date createdAt = new Date()

}

Now, create a regular domain class and extend it. 现在,创建一个常规域类并对其进行扩展。

package com.example.domain

import com.example.model.BaseClass

class SomeClass extends BaseClass {

    String name

    static constraints = {
        name(nullable: false)
    }

}

As you can see, once you persist SomeClass a createdAt field is filled and saved as well. 如您所见,一旦您持久化SomeClass,一个createdAt字段也会被填充并保存。 Check the test class out: 检查测试类:

@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"
    }
}

I hope it can be helpful. 我希望它会有所帮助。

I have just created class structure as yours (Grails 2.1.0) and there is no problem. 我刚刚创建了类结构(Grails 2.1.0)并且没有问题。 It works when mocked and unit-tested. 它在模拟和单元测试时有效。 The same when scaffolded and SomeClass and ThirdClass instances saved from forms. 当scaffolded和SomeClass和ThirdClass实例从表单中保存时也是如此。 Try clean your DB, especially if you haven't used 'create-drop' mode. 尝试清理您的数据库,特别是如果您没有使用'create-drop'模式。 Maybe there is some old constraint left. 也许还有一些旧约束。 Last thing, you haven't specified when the error occurs - on save (create or update)? 最后,您没有指定何时发生错误 - 保存(创建或更新)? It's rather not probable to get JDBC exception on property set, is it? 在属性集上获取JDBC异常是不太可能的,是吗? I don't remember for sure but it's possible that simple property isn't cascaded by default then try to save SomeClass instance before saving the ThirdClass instance. 我不记得肯定但是默认情况下可能没有级联简单属性,然后在保存ThirdClass实例之前尝试保存SomeClass实例。 Also you can auto-cascade instead of declaring simple property by use hasOne relation like: 您也可以使用hasOne关系自动级联而不是声明简单属性,如:

class ThirdClass {
    ...
    static hasOne = [baseProperty:BaseClass]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM