SpringBoot具有关系的持久实体

时间:2018-07-13 16:23:20

标签: spring spring-boot spring-data-jpa

我有两个这样的实体

@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中指定,但是由于实体之间的映射,我希望它知道这种关系。我想念什么?

1 个答案:

答案 0 :(得分:0)

好吧,它看起来像是无限递归。 Person很多 CarsCar有一个一个所有者,即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...;
}

在此示例中,我将使用一种方法单独更新它们。 当然,您需要同时自动连接PersonRepositoryCarRepository

更新:

如果您不解决任何问题,则需要具有以下JSON请求结构:

{
  "id": 1,
  "name": "Joe",
  "cars": [
    {
      "car_id": 1,
      "color": "red",
      "owner" : 
      {
        "id": "1"
      }
    },
    {
      "car_id": 2,
      "color": "blue",
      "owner" : 
      {
        "id": "1"
      }
    }
  ]
}