Я использовал 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. Это всегда кажется базовым типом.