Grails / GORM: создание необязательной связи «один к одному»

#grails #grails-orm #domain-model

#grails #grails-orm #модель домена

Вопрос:

Я разрабатываю систему, в которой сообщения / обсуждения между пользователями могут быть обновлены, чтобы стать билетами. В одном конкретном месте я пытаюсь создать необязательные отношения «один к одному», но сталкиваюсь с определенными проблемами. Ниже приведена сокращенная версия объектов, находящихся в центре внимания.

Правила:

  1. Сообщение может стать тикетом, если требуется. (необязательно)
  2. У билета должен быть Post. (обязательно)

Post.groovy

 class Post {

        String title
        String description
        String postedBy

        Ticket ticket

        static hasMany = [comments: Comment]

    static constraints = {
        title(blank:false)
        description(blank:false)
        postedBy(blank:false)
        ticket (nullable:true,unique:true)
    }
}
  

Ticket.groovy

 class Ticket {

        String title
        String description
        String postedBy

        Post post

        static hasMany = [responses: Response]

        static constraints = {
                title(blank:false)
                description(blank:false)
                postedBy(blank:false)
                post (nullable:false,unique:true)
        }

}
  

В какой-то степени это работает. Я могу:

  1. Создайте сообщение, оставив атрибут ticket нулевым, если и когда сообщение будет обновлено, чтобы стать билетом
  2. Я могу явно установить атрибут ticket сообщения, чтобы он указывал на родительский билет.

Однако это сопоставление не применяется на уровне домена. Это оставляет место для ситуации, когда Ticket1 указывает на Post1, но Post1 вместо этого указывает на Ticket2.

Я попытался использовать a static hasOne = [post: Post] в классе Ticket, но позже узнал, что он требует наличия a static belongsTo = [ticket: Ticket] в классе Post, и это становится обязательным отношением 1 к 1, что не то, что я ищу.

Есть ли способ добиться этого необязательного сопоставления 1 к 1 в этом сценарии? Любые указатели были бы наиболее полезными.

Комментарии:

1. Пожалуйста, закройте вопрос, если ответ на него вас удовлетворит. Спасибо! 🙂

2. Это не работает. Я не думаю, что 1-1 можно создать. Вероятно, я должен закрыть его как неопровержимый?

Ответ №1:

Вы могли бы рассмотреть возможность создания пользовательского средства проверки, например

 class Post {
  // Other fields

  Ticket ticket

  static constraints = {
    // Other constraints
    ticket (nullable:true,unique:true, validator: { val, obj ->
       if(val) {
         return val.post == obj
       }
    })
  }
}
  

Решит ли это вашу проблему?

Комментарии:

1. Привет, спасибо за ваше решение! Это работает (с небольшим внесенным изменением) и лучше, чем предыдущая ситуация, поскольку теперь есть проверка хотя бы на одном конце. Однако теперь все еще существует вероятность того, что я установлю правильный аргумент ticket в Post (поскольку средство проверки применяет его), но затем вернусь к Ticket и изменю объект Post, на который он указывает. Мне просто интересно, есть ли какой-либо способ обеспечить его соблюдение с обоих концов, но я думаю, что нет? 🙁

2. Как насчет другой проверки на другом конце? Это должно быть возможно?

3. Как вы пришли? Есть ли шанс, что вы закроете этот вопрос?

4. Привет, извините за задержку. Я пытался использовать валидатор на другом конце, но это создает конфликт, поскольку одно из значений должно быть установлено перед другим; продолжая попытки, вы скоро узнаете о результате.