我的任务非常简单, 我有一个“用户”实体。
此用户有大量字段,例如:
的firstName 年龄 国家 .....
我的目标是公开一个简单的控制器以进行更新:
@RequestMapping(value = "/mywebapp/updateUser")
public void updateUser(data)
我希望客户拨打我的控制器,其中包含可能包含一个或多个字段的更新。
实施此类方法的最佳做法是什么?
一个天真的解决方案是从客户端发送整个实体,并在服务器中覆盖所有字段,但这似乎非常低效。
另一个天真和糟糕的解决方案可能如下:
@Transactional
@RequestMapping(value = "/mywebapp/updateUser")
public void updateUser(int userId, String[] fieldNames, String[] values) {
User user = this.userDao.findById(userId);
for (int i=0 ; i < fieldsNames.length ; i++) {
String fieldName = fieldsName[i];
switch(fieldName) {
case fieldName.equals("age") {
user.setAge(values[i]);
}
case fieldName.equals("firstName") {
user.setFirstName(values[i]);
}
....
}
}
}
显然,这些解决方案并不严肃,必须有更强大的\通用方式(反思可能)。
有什么想法吗?
答案 0 :(得分:1)
我曾经用杰克逊做过遗传。它有一个非常方便的ObjectMapper.readerForUpdating(Object) method,它可以将JsonNode / Tree中的值读取到现有对象上。
控制器/服务
@PATCH
@Transactional
public DomainObject partialUpdate (Long id, JsonNode data) {
DomainObject o = repository.get(id);
return objectMapper.readerForUpdating(o).readValue(data);
}
就是这样。我们使用Jersey将服务公开为REST Web服务,因此使用@PATCH注释。 至于这是一个控制器还是一个服务:它处理原始传输数据(JsonNode),但为了有效地工作,它需要是事务性的(当事务提交时,读者所做的更改将被刷新到数据库中。同一事务允许hibernate仅动态更新已更改的字段。
答案 1 :(得分:0)
如果您的用户实体不包含任何安全字段(如登录名或密码),则只需将其用作模型属性即可。在这种情况下,所有字段都将自动从表单输入更新,那些不是要更新的字段,如id应该是表单上的隐藏字段。
如果您不想将所有实体属性公开给表示层,您可以使用pojo aka命令来映射用户实体所需的所有字段
BWT将控制器方法设置为事务性是非常糟糕的做法。您应该分离您的应用程序层。你需要有服务。这是@Transactional注释所属的层。你可以在crud操作之前完成所有逻辑。