2016-10-03 2 views
0

При миграции существующего приложения от Grails 2.5 до 3.1 я столкнулся с нечетной проблемой с двунаправленным взаимно однозначным отношением.Grails 3 hasOne nullability issue

Представьте себе простую модель с пользователем и Employee объектов. A User представляет собой общую учетную запись пользователя. Не все пользователи - это сотрудники, но все сотрудники - это пользователи. Кроме того, сотрудники имеют ссылки на менеджеров, руководителей и т. Д. (Также экземпляры пользователей). Пользователь является владением отношениями.

class User { 
    Employee employee 

    static mappedBy = [employee: "user"] 
    static hasOne = [employee: Employee] 

    static constraints = { 
    employee(nullable:true) 
    } 
} 

class Employee { 
    User user // represents employee's own account, a bi-directional one-to-one 
    User supervisor // represents a supervisor 

    static belongsTo = [user: User] 

    static constraints = { 
    user(unique:true) 
    supervisor(nullable:true) 
    } 
} 

Проблема после обновления до Grails 3 является то, что в режиме создания, это приводит к supervisor_id колонке таблицы сотрудников генерируется в NOT NULL, тогда как в Grails 2 это было обнуляемым, как и ожидалось (только с user_id быть NOT NULL,).

Я проверил это с Grails 3.1.12 и 3.2.0, получив одинаковое поведение с обоими. Я делаю что-то глупо в своих объявлениях класса домена? Я пробовал несколько сопоставлений, чтобы добиться такого же поведения, как в Grails 2.5, без везения. В некоторых случаях я даже получаю внешний ключ по обе стороны от отношений ...

ответ

0

Я не знаю, почему ваш код работал с предыдущей версией Grails, но это неправильно.

Когда вы используете hasMany и принадлежит, нет необходимости определять другое свойство в дочернем объекте, и вам не нужно также использовать свойство mappedBy для родителя, а также то же самое с родителем (свойство employee at Пользователь)

Grails не нуждается ни в чем другом, чтобы узнать, что является двунаправленным свойством для обеих кладок, а также для contraint user(unique : true).

Так что ваши классы должны выглядеть следующим образом:

class User { 

     static hasOne = [employee: Employee] 

     static constraints = { 
       employee(nullable: true) 
     } 
} 

class Employee { 
    User supervisor // represents a supervisor 
    static belongsTo = [user: User] 

    static constraints = { 
     supervisor(nullable:true) 
    } 
} 

Это может быть приятно знать, как ваша структура БД. Но таким образом все ключи иностранцев хранятся в таблице сотрудников. Но, конечно, вы можете перемещаться из обоих объектов. Если у вас есть другая структура, вы можете сопоставить свою текущую базу данных с этой моделью. См. this

employee.user 
user.employee 
+0

Благодарим за отзыв! Я пробовал ваш код в Grails 3.2.0, но он по-прежнему приводит к тому, что NOT NULL добавляется в столбец supervisor_id таблицы employee, несмотря на ограничение null: true. Что касается объекта mappedBy on User, это старый код из старого кода, где сопоставление «один-к-одному» было необязательным, а собственная сторона была наоборот (но внешний ключ всегда был на стороне пользователя) – Rado

+0

Важно отметить, что сам Grails чтит ограничение на nullable (даже с моим оригинальным «плохим» кодом), поэтому при запуске с существующей или созданной вручную схемой базы данных она работает так, как ожидалось. Но это схема hbm2ddl, которая генерируется некорректно, с NOT NULL, применяемой к этим столбцам, и это нарушает наши интеграционные тесты, выполняемые против базы данных в памяти H2. – Rado

+0

Добро пожаловать. Я попытаюсь воспроизвести его через несколько часов и дам вам знать. – quindimildev

Смежные вопросы