我有两个这样的实体
@Entity
public class Person {
@Id
private int id;
private String name;
@OneToMany(mappedBy="owner", cascase=CascadeType.ALL)
private List<Car> cars;
}
和
@Entity
public class Car {
@Id
private int car_id;
private String color;
@ManyToOne
@JoinColumn(name="person_id")
private Person owner;
}
因此,我们有两个具有某种关系的实体,一个人可以拥有许多汽车,而每辆汽车可以由一个人拥有。
但这是附加到restcontroller端点的,它在其中接收一些json,如:
{
"id": 1,
"name": "Joe",
"cars": [
{
"car_id": 1,
"color": "red",
},
{
"car_id": 2,
"color": "blue",
}
]
}
那么,一个有2辆车的人。端点就像
@RequestMapping(value={"/people"},
method=RequestMethod.PUT,
produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> updateApplication(@RequestBody Person personRequest) {
Person person = personRepo.save(personRequest);
return new ResponseEntity<>(person, HttpStatus.OK);
}
当此端点接收到上述json时,我希望它将请求对象保存到db中,包括根据需要处理插入/更新/删除。但是,我从数据库中得到一个错误,提示车主不能为空。我看到它没有在json中指定,但是由于实体之间的映射,我希望它知道这种关系。我想念什么?
答案 0 :(得分:0)
好吧,它看起来像是无限递归。
Person
有很多 Cars
。
Car
有一个一个所有者,即Person
。
只是一个建议:
检索实体时,Spring希望在Person
JSON结构中包含一个Car
(所有者),并在Car
中包含一个Person
的列表。如果要检索数据,可能会出现问题,因为它将创建无限递归。
您需要为LAZY
添加访存类型,以防止发生这种递归。
@OneToMany(mappedBy="owner", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
现在,正如我所说,对于您的问题,您的Car
需要有一个Person
,但是在您的请求中,您不需要指定Person
(所有者),因此Spring不知道主人是谁。这是主要问题。
我建议您单独更新它们:
@PutMapping("/people/{id}")
public ResponseEntity <?>handleUpdate(@PathVariable("id") Long personId, @RequestBody Person person) {
Optional <Person> personOptional = personRepository.findById(personId);
if (personOptional.isPresent()) {
Person owner = personOptional.get();
for (Car car: person.getCars()) {
car.setOwner(owner);
}
carRepository.saveAll(person.getCars());
person.setCars(null);
person.setId(personId);
personRepository.save(person);
}
return...;
}
在此示例中,我将使用一种方法单独更新它们。
当然,您需要同时自动连接PersonRepository
和CarRepository
更新:
如果您不解决任何问题,则需要具有以下JSON请求结构:
{
"id": 1,
"name": "Joe",
"cars": [
{
"car_id": 1,
"color": "red",
"owner" :
{
"id": "1"
}
},
{
"car_id": 2,
"color": "blue",
"owner" :
{
"id": "1"
}
}
]
}