Можно ли добавить DomainObject в качестве свойства CommandObject? - PullRequest
0 голосов
/ 27 июня 2018

Я использовал Grail CommandObject для хранения всей информации для страницы поиска. Нечто вроде

class SomeSearchCommand {
     User user
     ...
     Integer max=100
     Integer offset=0
}

А потом в контроллере

class SomeThingController {
    def search(SomeSearchCommand c) {
        // build a query based SomeSearchCommand
        Something.where {
            if (c.user) user==c.user
            ...
        }.list(max: c.max, offset: c.offset)
    } 
} 

Кажется, это работает хорошо, и когда вы вызываете действие с помощью

/someThing/search?user=3&offset=100

Находит все объекты SomeThing, принадлежащие пользователю 3.

Но во время игры с кодом я обнаружил, что если вы измените URL на

/someThing/search?user.id=3&user.name=ichangedyourname&offset=100

Тогда объект User внутри объекта домена будет загружен из базы данных с id = 3, и свойство user.name будет изменено. Объект User теперь помечен как грязный и был добавлен в сеанс. Если вы случайно выполнили некоторый код, который вызывает сброс (или для параметра flushMode установлено значение Auto), то изменение пользовательского объекта сохраняется.

Я нашел обходной путь, добавив @BindUsing вокруг объекта пользователя. Похоже, что это отключает глубокую привязку для объекта пользователя и позволяет привязывать только по параметру user, а не user.id

class SomeSearchCommand {
     @BindUsing({obj, source ->
          if (source['user'] instanceOf User) return source['user']
          if (source['user'] instanceOf serializable) return User.get(source['user'])
     })
     User user
     ...
     Integer max=100
     Integer offset=0
}

Другой обходной путь - просто не использовать объект домена пользователя в CommandObject.

class SomeSearchCommand {
     String userId
     User getUser() {
         return User.get(userId)
     }
     ...
     Integer max=100
     Integer offset=0
}

Это означает, что запрос URL должен измениться на /some/search?userId=3&offset=100

Но user все еще является свойством объекта команды, который возвращает типизированный объект.

Я впервые заметил это, используя grails 2.3.11 (где flushMode установлен на auto), так что внутренний объект домена всегда записывался в базу данных. В версии Grails после 2.4 режим сброса установлен на Вручную, поэтому измененный объект домена сохраняется только после сеанса.

Я не вижу примеров в документах Grails о размещении domainObject внутри commandObject. Это всегда кажется базовым типом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...