例如,
Person
与Addres
有多对一的关联。如果我们使用SDR v.2.5.6(Spring Boot v.1.4.3)进行PUT请求,则一切正常。但是,如果我们切换到版本2.5.7(即Spring Boot v.1.4.4),则会出现错误:
与其他类型的关联(例如单向和双向的一对多关联)也会发生相同的情况-请参见我的示例应用程序代码和测试。无法构造Address的实例:没有String-argument构造函数/工厂方法可用于从String值反序列化
这个问题存在于自Spring Boot 1.4.4以来的所有版本中,包括最新稳定的1.5.6版本,以及最新的2.0.0-SNAPSHOT版本!
为了解决这个问题,我们可以切换到SDR v.2.5.6(Spring Boot v.1.4.3)。
我已经准备好了一个Postman请求集合,以帮助您解决问题:SDR PUT Issue
更新 2017-08-14
我找到了如何避免错误Can not construct instance of Address: no String-argument constructor/factory method to deserialize from String value
。
由于我在这个项目中使用了Lombok,
只需要告诉Lombok抑制使用@ConstructorProperties
注释
generated constructors。
因此,我在“lombok.config”文件中设置了lombok.anyConstructor.suppressConstructorProperties=true
,错误就消失了。
不幸的是,发现了一个新问题 - PUT请求根本不会更新关联对象!
下面的示例演示了这一点。当我们尝试通过将其地址从addresses/1
(初始值)更改为addresses/2
来更新Person时 - 它仍然是相同的:addresses/1
!与前一个问题一样,这个问题存在于所有版本的Spring Boot自1.4.4(SDR - 自v.2.5.7)以来。
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"
}
}
}
检查 Person 的“新”地址 - 地址未更新:
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年8月24日
感谢Scott C.的answer,发现了SDR存在一个错误,具体描述在两个工单中:DATAREST-1001和DATAREST-1012。
http://localhost:8080/api/persons/1/address
(v.2.5.6) 的对象是什么? - Andrew Tobilko{ "街道": "地址1", "_links": { "自身": { "href": "http://localhost:8080/api/addresses/1" }, "地址": { "href": "http://localhost:8080/api/addresses/1" } } }
- Cepr0String
构造Address
实例。什么是BaseEntity
? - Andrew Tobilko