可以将DomainObject添加为CommandObject的属性吗?

时间:2018-06-27 15:37:47

标签: grails

我正在使用grails 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

它找到属于用户3的所有“ SomeThing”对象。

但是在玩代码时,我发现如果将URL更改为

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

然后,将从数据库中将id = 3加载到域对象内部的User对象,并更改user.name属性。用户对象现在被标记为脏对象,并已添加到会话中。如果您碰巧执行一些调用刷新的代码(或将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)注意到了这一点,因此内部域对象始终被写入数据库。 在2.4之后的grails版本中,刷新模式设置为“手动”,因此修改后的域对象仅在刷新会话时持久存在。

我没有在grails文档中看到有关将domainObject放在commandObject内的任何示例。它似乎总是基本类型。

0 个答案:

没有答案