从版本 2.5.7开始, Spring Data REST无法正确执行 PUT 请求以更新 具有关联资源的资源 。与PATCH请求不同,它可以按预期工作!
例如,与Person有多对一关联Addres。如果我们使用SDR v.2.5.6(Spring Boot v.1.4.3)执行PUT请求,则一切正常。但是,如果我们切换到版本2.5.7(即Spring Boot v.1.4.4),则会收到错误消息:
Person
Addres
无法构造Address的实例:没有要从String值反序列化的String-argument构造函数/工厂方法
其他类型的关联也会发生同样的情况,例如一对多(单向和双向)关联-请参阅我的 示例应用程序 代码和测试。
从1.4.4开始的 所有 版本的Spring Boot 中 都 存在此问题,包括最新的稳定的1.5.6版本以及最新的2.0.0-SNAPSHOT版本!
要解决这种情况,我们可以切换到SDR v.2.5.6(Spring Boot v.1.4.3)。
我已经准备好 邮递员要求的集合, 以帮助您解决此问题:SDR PUT问题
更新2017-08-14
我找到了避免错误的方法Can not construct instance of Address: no String-argument constructor/factory method to deserialize from String value。
Can not construct instance of Address: no String-argument constructor/factory method to deserialize from String value
由于我在该项目中使用Lombok,因此仅需告诉Lombok禁止@ConstructorProperties在生成的构造函数中使用注释即可 。所以我lombok.anyConstructor.suppressConstructorProperties=true在“ lombok.config”文件中设置,错误消失了。
@ConstructorProperties
lombok.anyConstructor.suppressConstructorProperties=true
不幸的是,发现了一个 新问题 -PUT请求根本不更新关联的对象 !
下面的示例演示了这一点。当我们试图从改变自己的地址,更新的人addresses/1(初始值)addresses/2-那么它仍然是相同的:addresses/1!与以前的问题一样,自1.4.4(SDR-v.2.5.7起)以来, 所有 版本的Spring Boot 中 都 存在此问题。
addresses/1
addresses/2
我调试了项目,发现问题的原因隐藏在方法中DomainObjectReader#mergeForPut(请参见其源代码)-它 永远不会 用新资源替换关联的资源。
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.的回答,事实证明SDR有一个 错误 ,该错误 在两张票中进行了描述:DATAREST-1001和DATAREST-1012。
该问题似乎已被报告为错误:-请验证。据我所知,这就是您在上面报告的问题。
注意,我正在将以前的答案修改为此错误报告。