Spring Data REST - PUT 请求自 v.2.5.7 起无法正常工作
由于版本2.5.7 Spring Data REST无法正确执行PUT请求以更新具有关联资源的资源。与按预期工作的 PATCH 请求不同!
例如,与 具有多对一关联。如果我们使用 SDR v.2.5.6(Spring Boot v.1.4.3)执行 PUT 请求,则一切正常。但是,如果我们切换到版本2.5.7(即Spring Boot v.1.4.4),那么我们会收到一个错误:Person
Addres
无法构造地址的实例:没有字符串参数构造函数/工厂方法从字符串值反序列化
其他类型的关联也是如此,例如一对多(单向和双向)关联 - 请参阅我的示例应用程序代码和测试。
自1.4.4以来,所有版本的Spring Boot都存在此问题,包括最新的稳定版1.5.6版本以及最新的2.0.0-SNAPSHOT版本!
要解决此问题,我们可以切换到SDR v.2.5.6(Spring Boot v.1.4.3)。
我准备了一个Postman请求集合来帮助您解决问题:SDR PUT问题
更新 2017-08-14
我发现了如何避免错误。Can not construct instance of Address: no String-argument constructor/factory method to deserialize from String value
由于我在这个项目中使用龙目岛,所以有必要告诉龙目岛在生成的构造函数中使用注释来抑制。所以我设置了“lombok.config”文件,错误消失了。@ConstructorProperties
lombok.anyConstructor.suppressConstructorProperties=true
不幸的是,发现了一个新问题 - PUT请求根本不会更新关联的对象!
下面的示例演示了这一点。当我们尝试通过将他的地址从(初始值)更改为 - 来更新Person时,它保持不变:!除了上一个问题之外,自1.4.4(SDR - 来自v.2.5.7)以来的所有版本的Spring Boot中都存在这个问题。addresses/1
addresses/2
addresses/1
我调试了我的项目,发现问题的原因隐藏在方法中(请参阅其源代码) - 它永远不会用新资源替换关联的资源。DomainObjectReader#mergeForPut
在我将此问题发布到Spring JIRA之前,如果您的项目中有此问题以及您对此有何看法,请在此处报告。
你可以在这里得到我的测试,并在你的项目中检查它 - 测试是“独立的”,不依赖于其他类/模块(我希望只排除H2)。
@Entity
public class Person {
private String name;
@ManyToOne
private Address address;
// other stuff
}
@Entity
public class Address {
private String street;
// other stuff
}
尝试更新人员:
PUT http://localhost:8080/api/persons/1
{
"name": "person1u",
"address": "http://localhost:8080/api/addresses/2"
}
获取正确的响应:
{
"name": "person1u",
"_links": {
"self": {
"href": "http://localhost:8080/api/persons/1"
},
"person": {
"href": "http://localhost:8080/api/persons/1"
},
"address": {
"href": "http://localhost:8080/api/persons/1/address"
}
}
}
然后检查“新”人员地址 - 地址未更新:
GET http://localhost:8080/api/persons/1/address
{
"street": "address1",
"_links": {
"self": {
"href": "http://localhost:8080/api/addresses/1"
},
"address": {
"href": "http://localhost:8080/api/addresses/1"
}
}
}
更新 2017-08-24
多亏了Scott C. answer,事实证明SDR有一个错误,在两个票证中描述了这一点:DATAREST-1001和DATAREST-1012。