Grails 3 hasOne nullability issue

При переносе существующего приложения с Grails 2.5 на 3.1 я столкнулся со странной проблемой с двусторонним отношением «один к одному».

Представьте себе простую модель с пользователем и 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 заключается в том, что в режиме create это приводит к supervisor_idтому , что столбец таблицы employee генерируется какNOT NULL, в то время как в Grails 2 он был nullable как ожидалось (только user_id не является NULL).

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

1 ответ

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

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

    Grails не нужно ничего другого, чтобы знать, что является двунаправленным свойством на обоих классах, и противопоставление 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)
        }
    }
    

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

    employee.user
    user.employee