简体   繁体   English

Spring JPA - 实体的 RESTful 部分更新和验证

[英]Spring JPA - RESTful partial update and validation for entity

I've a simple RESTful API based on Spring MVC using a JPA connected MySQL database.我有一个基于 Spring MVC 的简单 RESTful API,使用 JPA 连接的 MySQL 数据库。 Until now this API supports complete updates of an entity only.到目前为止,此 API 仅支持实体的完整更新。 This means all fields must be provided inside of the request body.这意味着必须在请求正文中提供所有字段。

@ResponseBody
@PutMapping(value = "{id}")
public ResponseEntity<?> update(@Valid @RequestBody Article newArticle, @PathVariable("id") long id) {

    return service.updateById(id, newArticle);
}

The real problem here is the validation, how could I validate only provided fields while still require all fields during creation?这里真正的问题是验证,我怎么能只验证提供的字段,而在创建过程中仍然需要所有字段?

@Entity
public class Article {

    @NotEmpty @Size(max = 100) String title;
    @NotEmpty @Size(max = 500) String content;

    // Getters and Setters
}

Example for a partial update request body {"content": "Just a test"} instead of {"title": "Title", "content": "Just a test"} .部分更新请求正文的示例{"content": "Just a test"}而不是{"title": "Title", "content": "Just a test"} The actual partial update is done by checking if the given field is not null:实际的部分更新是通过检查给定字段是否不为空来完成的:

if(newArticle.getTitle() != null) article.setTitle(newArticle.getTitle());

But the validation of course wont work!但是验证当然不起作用! I've to deactivate the validation for the update method to run the RESTful service.我必须停用更新方法的验证才能运行 RESTful 服务。 I've essentially two questions:我基本上有两个问题:

  • How can I validate only a "existing" subset of properties in the update method while still require all fields during creation?如何在更新方法中仅验证“现有”属性子集,同时在创建过程中仍然需要所有字段?
  • Is there a more elegant way for update partially then checking for null?是否有更优雅的方式进行部分更新然后检查空值?

The complexity of partial updates and Spring JPA is that you may send half of the fields populated, and even that you will need to pull the entire entity from the data base, then just "merge" both entity and the pojo, because otherwise you will risk your data by sending null values to the database. 部分更新和Spring JPA的复杂性在于,您可能会发送填充的一半字段,甚至您将需要从数据库中提取整个实体,然后只需“合并”实体和pojo,否则您将通过向数据库发送空值来冒险数据。

But merging itself is kind of tricky, because you need to operate over each field and take the decision of either send the new value to the data base or just keep the current one. 但是合并本身有点棘手,因为您需要对每个字段进行操作并做出将新值发送到数据库或仅保留当前值的决定。 And as you add fields, the validation needs to be updated, and tests get more complex. 在添加字段时,需要更新验证,并且测试变得更加复杂。 In one single statement: it doesn't scale . 在一个简单的声明中: 它不会缩放 The idea is to always write code which is open for extension and closed for modifications. 想法是始终编写开放的代码以进行扩展,封闭的代码以进行修改。 If you add more fields, then the validation block ideally doesn't need to change. 如果添加更多字段,则理想情况下无需更改验证块。

The way you deal with this in a REST model, is by operating over the entire entity each time you need. 在REST模型中处理此问题的方式是,每次需要时都对整个实体进行操作。 Let's say you have users, then you first pull a user: 假设您有用户,然后先拉一个用户:

GET /user/100

Then you have in your web page the entire fields of user id=100. 然后,您的网页中将具有用户ID = 100的所有字段。 Then you change its last name. 然后,您更改其姓氏。 You propagate the change calling the same resource URL with PUT verb: 您传播使用PUT动词调用相同资源URL的更改:

PUT /user/100

And you send all the fields, or rather the "same entity" back with a new lastname. 然后,您以新的姓氏发送回所有字段,或更确切地说是“相同实体”。 And you forget about validation, the validation will just work as a black box. 您会忘记验证,验证将只不过是一个黑匣子。 If you add more fields, you add more @NotNull or whatever validation you need. 如果添加更多字段,则添加更多@NotNull或所需的任何验证。 Of course there may be situations where you need to actually write blocks of code for validation. 当然,在某些情况下,您需要实际编写代码块进行验证。 Even in this case the validation doesn't get affected, as you will have a main for-loop for your validation, and each field will have its own validator. 即使在这种情况下,验证也不会受到影响,因为您将有一个用于验证的主for循环,并且每个字段都有自己的验证器。 If you add fields, you add validators, but the main validation block remains untouchable. 如果添加字段,则添加验证器,但是主验证块仍然不可触摸。

Those are the most basic options for entity validation: 这些是实体验证的最基本选项:

  1. You can annotate column with @NotNull , just as you did with other constraints. 您可以使用@NotNull注释列,就像使用其他约束一样。
  2. You can annotate the field with @Column(nullable = false) . 您可以使用@Column(nullable = false)注释字段。

@Valid on the other hand validates object before entering the method. 另一方面,@ @Valid在输入方法之前先验证对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM