如何仅更新已更改的属性 - Spring MVC

Posted

技术标签:

【中文标题】如何仅更新已更改的属性 - Spring MVC【英文标题】:How to update only attributes that have changed - Spring MVC 【发布时间】:2016-05-23 06:54:30 【问题描述】:

我的控制器

@RequestMapping(value = "/user/id", method = RequestMethod.GET)
public String updateUserById(@PathVariable("id") Long id, Model model) 
    User user = userRepository.findOne(id);
    model.addAttribute(user);
    return "admin/editUser";


@RequestMapping(value = "/user/id", method = RequestMethod.POST)
@ResponseBody
public String updateUserById(@PathVariable("id") Long id, @ModelAttribute User user) 
    userRepository.updateUser(id, user); // with a try catch

@Override
public void updateUser(Long id, User user) 
    User userDB = userRepository.findOne(id);
    userDB.setFirstName(user.getFirstName());
    userDB.setLastName(user.getLastName());
    userDB.setEmail(user.getEmail());
    userDB.setUsername(user.getUsername());
    userRepository.save(userDB);

这种方法有效,但对我来说很难看。假设用户刚刚更改了视图中的名字字段,我该如何调整我的代码只调用函数来设置名字?

类似于观察者模式来通知有变化的字段?

【问题讨论】:

你使用休眠? 是的,我使用的是休眠,更准确地说是 spring-boot-starter-data-jpa 查看我下面的答案,使用 dynamicUpdate=true。它只会更新更改的值。 使用 spring-data-jpa,并拥有一个扩展 CrudRepository 的存储库,您应该能够使用已设置的 ID 保存您的实体,并且 spring-data 将覆盖具有相同 ID 的实体。无需单独设置实体的属性。请参阅下面帕特里克的回答。 【参考方案1】:

如果您使用的是休眠,那么休眠dynamicUpdate = true 中有一个属性将只更新数据库中的更新字段

如下代码

@Entity
@Table(name = "User")
@org.hibernate.annotations.Entity(
        dynamicUpdate = true
)
public class User 

对于 hibenrate 4 + 使用这些

@DynamicInsert(true)
@DynamicUpdate(true)

【讨论】:

我只需要注释吗?我问这个是因为我的 updateUser 方法仍在设置所有字段。但我同意这将减少对“.save()”方法的数据库查询。 没有。没有办法只设置更新的数据。因为用户应该拥有所有数据。因为最终它将在数据库中更新,所以休眠需要所有数据,否则如果用户没有属性值,休眠将更新 null..【参考方案2】:

我想你的代码是这样工作的:

用户想要更改他的user entity 的一些数据。意味着在前端你已经向他展示了他所有来自数据库用户表的条目,比如名字、姓氏等。

例如,用户更改了他的名字并点击了保存按钮。您的控制器收到用户实体包括 user.id、新名字和所有旧设置值。如果您的代码是这样工作的,您可以轻松地save() 用户实体。无需先从数据库中获取用户。

所以就这样做吧:

@Override
public void updateUser(User user) 
    userRepository.save(user);

Repository 知道用户实体的 Id 并更新完整的实体。

由于您的用户实体中没有 ID,因此请使用控制器中的 ID,如下所示:

@Override
public void updateUser(User user, Long Id) 
    user.setId(Id);
    userRepository.save(user);

【讨论】:

感谢您的解释! 它没有回答这个问题。问题是:“如何仅更新已更改的属性”。答案仍然是更新 userRepository.save(...) 中的属性。它只是不做集合,但在后台会发生对数据库的集合。示例:user.firstName = 'lolo',用户想更改 user.lastName='koko'。但@trudy 拦截它并更改名字。更新将同时改变 @lolo 也许它没有回答 100% 的问题,但这正是他寻找的解决方案。因为他不想要updateUser 的“丑陋”方法。所以不知道否决票是否合理。 @Patrick 问题背后的想法不是代码约定,而是数据完整性。

以上是关于如何仅更新已更改的属性 - Spring MVC的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5.3更新记录。仅更新已更改的记录并保留未更改的记录

[DataGridCheckBoxColumn在属性更改时不会在MVVM中更新

仅查看Model OnPropertyChanged上的更新,但不查看ViewModel OnPropertyChanged中的更新

Django:仅更新UpdateView中已更改的字段

如何使用本地缓存并仅使用 Firestore 更新更改的文档?

Django Model Formset:仅跟踪集合中已更新/保存的那些项目的更改?