Плагин Fixtures Исключения ссылочной целостности в Grails

У меня есть объект Foo, который имеет двунаправленную связь один-к-одному с Bar, а другой - с Baz. Когда я пытаюсь сделать .load с помощью Foo и даю ему только Bar, я получаю исключения ссылочной целостности с жалобами на отсутствие Baz.

Так ли это на самом деле? Разве в реальной среде невозможно, чтобы в базе данных не было подходящего объекта Baz?

Я попытался вручную установить baz: null в закрытии загрузки фикстур, но все равно получаю то же самое. Кстати, когда я устанавливаю только свойства (например, простую строку), все работает нормально. Это только когда я начинаю устанавливать отношения.

Это с Grails 2.2.4, Fixtures 1.2 и без установленного плагина build-test-data.

ИЗМЕНИТЬ: у меня есть ограничения, в которых Baz должен иметь значение NULL и быть уникальным. Просто для смеха я попытался добавить ограничение blank, но безуспешно.

static constraints = {
    baz nullable:true, unique: true, blank: true
}

ИЗМЕНИТЬ 2. Вот упрощенная версия кода:

class Foo {
    String someValue1
    String someValue2
    String whatever
    Bar bar
    Baz baz
    static mapping = {
        id composite: ['someValue1', 'someValue2'], generator: 'assigned'
        columns {
            bar([:]) { column name: 'some_other_value' }
            baz ([insertable:false, updateable: false]) {
                column name: 'some_value_1'
                column name: 'some_value_2'
            }
    }

    version: false

    static constraints = {
        //there are no constraints for Bar
        baz nullable:true, unique:true
    }
}

class Bar {
     String someOtherValue
     static hasMany = [foos:Foo]
     static mapping = { 
        id generator:'assigned', name:'someOtherValue'
     }
}

class Baz {
    String someValue1
    String someValue2
    String asdf

    static mapping = {
        id composite: ['some_value_1', 'some_value_2']
        version false
    }
}

class MyTest {
    def fixtureLoader
    @Before
    void setup() {
        fixureLoader.load {
            myBar(Bar, someOtherValue:"shibby")
            myFoo(Foo, someValue1:"test", someValue2:"test2", bar:myBar)
            //i also tried this
            //myFoo(Foo, someValue1:"test", someValue2:"test2", bar:myBar, baz:null)
        }
    }
}

Вот часть исключения:

Вызвано: org.h2.jdbc.JdbcBatchUpdateException: нарушение ограничения ссылочной целостности: «FK190E74B120F4F2BC: MYSCHEMA.FOO FOREIGN KEY (SOME_VALUE_1, SOME_VALUE_2) REFERENCES MYSCHEMA.BALUE_2; Оператор SQL: вставить в MYSCHEMA.foo (все, some_other_value, some_value_2, some_value_1) значения (?,?,?,?,?,?,?,?) [23506-164]

РЕДАКТИРОВАТЬ: извините, я оговорился ранее. Бар имеет отношения «многие к одному» с Фу.


person Alex Beardsley    schedule 08.08.2013    source источник
comment
Можете ли вы опубликовать простой пример неудачи? Классы доменов и приспособления помогут   -  person tim_yates    schedule 09.08.2013
comment
Ладно, только что выложил.   -  person Alex Beardsley    schedule 09.08.2013
comment
У вас ID на панели установлен на generator:'assigned', но я нигде не вижу, чтобы значение id было установлено. Это приводит к тому, что Bar не может сохраниться, что затем вызовет ограничение ссылочной целостности при сохранении Foo?   -  person proflux    schedule 09.08.2013
comment
myBar (Bar, someOtherValue: shibby) Это не установка идентификатора?   -  person Alex Beardsley    schedule 09.08.2013
comment
Что hasMany делает в баре с двусторонней связью один-к-одному?   -  person dmahapatro    schedule 20.08.2013


Ответы (1)


Ваша упрощенная версия кода (кроме hasMany в Bar) работает у меня без исключения FK. Хотя я бы предпочел другой подход для достижения истинных двунаправленных отношений «один-один», если я прав с отображением родительского и дочернего элементов.

Ниже представлена ​​моя установка, которая отлично работает без исключения ограничения FK. Обратите внимание, что я также упомянул в комментариях, как я могу достичь истинного двунаправленного взаимодействия, предполагая, что Foo имеет одну панель и одну базу.

class Foo implements Serializable{
    String someValue1
    String someValue2
    String whatever

    //True one to one can be achieved by doing as below
    //static hasOne = [bar: Bar, baz: Baz]

    Bar bar
    Baz baz

    static mapping = {
        id composite: ['someValue1', 'someValue2'], generator: 'assigned'
        columns {
            bar([:]) { column name: 'some_other_value' }
            baz ([insertable:false, updateable: false]) {
                column name: 'some_value_1'
                column name: 'some_value_2'
            }
        }
        version: false
    }

    static constraints = {
        //baz nullable:true, unique:true
    }
}

class Bar {
    String someOtherValue

    //True one to one can be achieved by doing as below
    //Below entry makes the relation bi-directional
    //Foo foo

    static mapping = {
        id generator:'assigned', name:'someOtherValue'
        //Optional, added for clarity
        someOtherValue column: 'some_other_value'
    }
}

class Baz implements Serializable{
    String someValue1
    String someValue2
    String asdf

    //True one to one can be achieved by doing as below
    //Below entry makes the relation bi-directional
    //Foo foo

    static mapping = {
        id composite: ['someValue1', 'someValue2']
        //Optional, added for clarity
        someValue1 column: 'some_value_1'
        someValue2 column: 'some_value_2'
        asdf column: 'asdf'

        version false
    }
}

class MyTests extends GroovyTestCase {
    def fixtureLoader

    void setUp() {
        fixtureLoader.load {
            myBar(Bar, someOtherValue:"shibby")
            myFoo(Foo, someValue1:"test", someValue2:"test2", 
                     whatever: "whatever", bar: myBar)
        }
    }

    void testSomething() {
        Foo.all.each{println it.properties}
        Bar.all.each{println it.properties}
    }
}

//Bootstrap Test in Dev mode
new Bar(someOtherValue: 'shibby').save()
new Foo(someValue1:"test", someValue2:"test2", 
        whatever: "whatever", bar: myBar).save(failOnError: true, flush: true)

Примечания

  • Выше я использовал ваш точный упрощенный код, но отношение hasMany в Bar.
  • Ограничения на Baz необязательны.
  • Светильники работают как положено.
  • Столбцы создаются в Foo, как и ожидалось.
  • logSql показал ожидаемый DML.
  • Чтобы увидеть изменения в таблице, я также использовал BootStraped те же тестовые данные в режиме разработки после run-app. Я смог увидеть ожидаемую структуру таблицы с данными в ней, используя dbconsole.
  • Следуя общему способу однозначного двунаправленного (упомянутого как закомментированный код), FK создаются в дочерних таблицах [Bar и Baz], поэтому явное сопоставление, которое вы предоставили в примере кода, не годится.
  • Вопрос станет более ясным, если будет упомянута сторона отношения собственности и обоснование наличия hasMany в Bar.
person dmahapatro    schedule 20.08.2013
comment
Я исправил это, изменив отношения между Foo и Baz на истинные отношения один-к-одному, как вы предложили. То есть static hasOne = [baz: Baz] в Foo и поле Foo в Baz. Спасибо, что попробовали это на самом деле; иногда нужно, чтобы кто-то сказал, что у меня это работает :) - person Alex Beardsley; 21.08.2013
comment
@AlexBeardsley Рад, что это было полезно. - person dmahapatro; 22.08.2013