一尘不染

Spring部分更新对象数据绑定

spring

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

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

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

{"id":"1", "displayName":"jim"}

当前,我们在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);
    ...
}

此处的代码有效,但存在一些问题:@RequestBody新建一个updateUser,并填写iddisplayNameCustomObjectMerger将其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){
....
}

我已经考虑过重新编写代码,customObjectMerger()使其更适合与JSON一起使用,进行计数并仅考虑来自的字段HttpServletRequest。但是,即使customObjectMerger()spring几乎提供了我所要查找的内容,甚至缺少JSON功能,但即使不得不首先使用a也会感到很棘手。如果有人知道如何让Spring做到这一点,我将不胜感激!


阅读 291

收藏
2020-04-17

共1个答案

一尘不染

我刚遇到同样的问题。我当前的解决方案如下所示。我还没有做过多的测试,但是经过初步检查,它似乎运行良好。

@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);
}

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

希望这对某人有帮助,

编辑:

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

2020-04-17