Spring部分更新对象数据绑定

Sam*_*sla 24 java spring spring-mvc

我们正在尝试在Spring 3.2中实现一个特殊的部分更新功能.我们使用Spring作为后端,并有一个简单的Javascript前端.我无法找到满足我们要求的直接解决方案,即update()函数应该采用任意数量的字段:值并相应地更新持久性模型.

我们对所有字段进行内联编辑,因此当用户编辑字段并确认时,id和修改后的字段将作为json传递给控制器​​.控制器应该能够从客户端(1到n)接收任意数量的字段并仅更新这些字段.

例如,当id == 1的用户编辑他的displayName时,发布到服务器的数据如下所示:

{"id":"1", "displayName":"jim"}
Run Code Online (Sandbox Code Playgroud)

目前,我们在UserController中有一个不完整的解决方案,如下所述:

@RequestMapping(value = "/{id}", method = RequestMethod.POST )
public @ResponseBody ResponseEntity<User> update(@RequestBody User updateUser) {
    dbUser = userRepository.findOne(updateUser.getId());
    customObjectMerger(updateUser, dbUser);
    userRepository.saveAndFlush(updateUuser);
    ...
}
Run Code Online (Sandbox Code Playgroud)

这里的代码有效,但有一些问题:@RequestBody创建一个新的updateUser,填充iddisplayName.CustomObjectMerger将其updateUserdbUser数据库中的相应内容合并,更新其中包含的唯一字段updateUser.

问题是Spring updateUser使用默认值和其他自动生成的字段值填充了一些字段,这些字段值在合并时会覆盖我们所拥有的有效数据dbUser.明确声明它应该忽略这些字段不是一个选项,因为我们希望我们update也能够设置这些字段.

我正在寻找一些方法让Spring自动合并显式发送到update()函数中的信息dbUser(不重置默认/自动字段值).有没有简单的方法来做到这一点?

更新:我已经考虑过以下选项,它几乎可以满足我的要求,但并不完全.问题是它需要更新数据,@RequestParam而(AFAIK)不执行JSON字符串:

//load the existing user into the model for injecting into the update function
@ModelAttribute("user")
public User addUser(@RequestParam(required=false) Long id){
    if (id != null) return userRepository.findOne(id);
    return null;
}
....
//method declaration for using @MethodAttribute to pre-populate the template object
@RequestMapping(value = "/{id}", method = RequestMethod.POST )
public @ResponseBody ResponseEntity<User> update(@ModelAttribute("user") User updateUser){
....
}
Run Code Online (Sandbox Code Playgroud)

我已经考虑过customObjectMerger()用JSON 重写我的工作更合适,计算并考虑到只有来自的字段HttpServletRequest.但是,customObjectMerger()当春天提供几乎正是我正在寻找的东西时,即使不得不首先使用a也会感到hacky ,减去缺少的JSON功能.如果有人知道如何让Spring做到这一点,我将非常感激!

Tyl*_*man 23

我刚遇到同样的问题.我目前的解决方案是这样的.我还没有做太多的测试,但是在初步检查时,它看起来工作得相当好.

@Autowired ObjectMapper objectMapper;
@Autowired UserRepository userRepository;

@RequestMapping(value = "/{id}", method = RequestMethod.POST )
public @ResponseBody ResponseEntity<User> update(@PathVariable Long id, HttpServletRequest request) throws IOException
{
    User user = userRepository.findOne(id);
    User updatedUser = objectMapper.readerForUpdating(user).readValue(request.getReader());
    userRepository.saveAndFlush(updatedUser);
    return new ResponseEntity<>(updatedUser, HttpStatus.ACCEPTED);
}
Run Code Online (Sandbox Code Playgroud)

ObjectMapper是一个类型为org.codehaus.jackson.map.ObjectMapper的bean.

希望这有助于某人,

编辑:

遇到了与子对象有关的问题.如果子对象收到要部分更新的属性,则会创建一个新对象,更新该属性并进行设置.这会擦除该对象上的所有其他属性.如果我遇到一个干净的解决方案,我会更新.