Spring和Hibernate - 通用实体更新

时间:2014-08-17 10:09:14

标签: java database spring hibernate reflection

我的任务非常简单, 我有一个“用户”实体。

此用户有大量字段,例如:

的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]);
          }
          ....
        } 
    }
}

显然,这些解决方案并不严肃,必须有更强大的\通用方式(反思可能)。

有什么想法吗?

2 个答案:

答案 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操作之前完成所有逻辑。