加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

在java REST API中,使用PATCH与PUT更新实体

发布时间:2020-12-15 01:41:29 所属栏目:大数据 来源:网络整理
导读:我即将开始在Java中使用新的rest api进行开发. 我的问题是关于PATCH的使用 为什么? 可以说,我们有一个名为Address.java的实体 public class Address { @Id private Long id @NotNull private String line1; private String line2; //optional @NotNull priv

我即将开始在Java中使用新的rest api进行开发.
我的问题是关于PATCH的使用 – 为什么?

可以说,我们有一个名为Address.java的实体

public class Address {

    @Id
    private Long id

    @NotNull
    private String line1;

    private String line2;       //optional

    @NotNull
    private String city;

    @NotNull
    private String state;   
}

要创建一个新地址,我会做这个http请求:

POST http://localhost:8080/addresses

满足以下要求:

{
    "line1" : "mandatory Address line 1","line2" : "optional  Address line 2","city"  : "mandatory City","state" : "cd"
}

假设创建的记录具有id 1

相应的@RestController AddressResource.java将具有以下方法:

@PostMapping(value = "/addresses")
public ResponseEntity

@valid将确保在将数据存储到表中之前实体有效.

现在假设,我从上面的公寓搬到街上的房子.如果我使用PATCH,它就会变成

PATCH http://localhost:8080/addresses/1

请求有效负载:

{
    "line1" : "1234 NewAddressDownTheStreet ST","line2" : null
}

相应的@RestController方法是:

@PatchMapping(value = "/addresses/{id}")
public ResponseEntity

现在,如果你查询表,我的地址不是吗?

"line1" : "1234 NewAddressDownTheStreet ST",<-- INCORRECT. Should be null.
"city"  : "mandatory City","state" : "cd"

可以看出,上述更新导致line2的值不正确.
这是因为在java中,在实例化类时,Address类中的所有实例变量都被初始化为null(如果它们是基元,则为默认初始值).因此无法区分line2被更改为null与默认值.

问题1)有没有一种标准的解决方法?

另一个缺点是,我不能使用@Valid注释来验证入口点的请求 – 因为它只是部分的.因此,无效数据可能会进入系统.

例如,假设有一个具有以下定义的附加字段:

@Min(0) 
@Max(100)
private Integer lengthOfResidencyInYears,

并且用户不小心打了190(当他们真的意味着19年)时,它不会失败.

如果我使用了PUT,客户端需要发送完整的地址对象,而不是PATCH.
这样做的好处是我可以使用@Valid来确保地址确实有效

如果有一个前提是在进行任何更新之前必须始终完成GET,为什么不能使用PUT而不是PATCH?
我错过了什么吗?

在旁边

我的结论是使用动态类型语言的开发人员是使用PATCH的支持者,因为从静态类型语言行Java或C#中使用它看不出任何好处.它似乎增加了更多的复杂性.

最佳答案
使用PATCH上传现有对象的修改版本几乎总是有问题的,正是您所概述的原因.如果你想使用带有JSON的PATCH,我强烈建议你遵循RFC 6902或RFC 7396.我不会说7396因为我不熟悉它,但是要遵循6902你将为PATCH操作定义一个单独的资源.在您给出的示例中,它看起来像:

PATCH http://localhost:8080/addresses/1
[
    { "op": "replace","path": "/line1","value": "1234 NewAddressDownTheStreet ST" },{ "op": "remove","path": "/line2" }
]

然后,您将处理此过程,生成一个以当前服务器状态启动的新实体对象,并在PATCH中应用更改.对新实体对象运行验证.如果通过,则将其推送到数据层.如果失败,则返回错误代码.

如果PUT不会增加太多开销,那么这是一个好主意.幂等是一件好事.权衡是您通过网络推送更多数据.如果您的资源不是很大而且不经常访问,那可能不是什么大问题.如果您的资源很大并且经常被访问,那么这可能会增加很多开销.当然,我们不能告诉你引爆点.

您似乎也已将资源模型完全绑定到数据库模型.对于非平凡的项目,良好的数据库表设计和良好的资源设计通常看起来非常不同.我知道很多框架会让你朝这个方向发展,但是如果你没有认真考虑将它们解耦,你可能会想要.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读