我有一个名为Person
的实体的Spring Boot应用程序,该实体具有@ManyToOne
的关系:
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
@ManyToOne
private Country country;
// ...
}
PersonController
用于允许GET
现有人员和POST
新人员:
@RestController
public class PersonController {
private final PersonRepository personRepository;
@Autowired
public PersonController(final PersonRepository personRepository) {
this.personRepository = personRepository;
}
@GetMapping("/person/{personId}")
public Person getPerson(@PathVariable long personId) {
return personRepository.findById(personId).get();
}
@PostMapping("/person_save_and_return_by_id")
public Person personSaveAndReturnById(@RequestBody Person person) {
Person savedPerson = personRepository.save(person);
// the payload sent by the client does not necessarily include all
// properties of the Country class, it might contain just the id.
// Therefore, we fetch the person from the database, so that all
// necessary JOIN operations are made and no properties are set to null.
Person samePerson = personRepository.findById(savedPerson.getId()).get();
return samePerson;
}
}
我想POST
个新朋友,而不必完整描述现有的Country
,我只想表示其ID:
curl -i -X POST -H "Content-Type:application/json" -d '{"firstName": "Frodo", "lastName": "Baggins", "country": {"id": 1}}' http://localhost:8080/person_save_and_return_by_id
不幸的是,返回的实体具有除ID之外的所有国家/地区属性,均设置为null:
{
"firstName" : "Frodo",
"id" : 4,
"lastName" : "Baggins",
"country" : {
"id" : 1,
"description" : null,
"countryCodeIso" : null
}
}
POST请求将所有内容插入数据库。例如,如果我GET
我先前发布的对象:
curl -i http://localhost:8080/person/4
返回的json看起来应该完全一样:
{
"lastName" : "Baggins",
"firstName" : "Frodo",
"country" : {
"id" : 1,
"countryCodeIso" : "FR",
"description" : "France"
},
"id" : 4
}
但这对我没有帮助,因为我需要使用创建新Country
的相同方法访问Person
实例。
我的问题是,当完全相同的人在@PostMapping
中没有这些空值时,为什么新建的人在@GetMapping
方法中有一个将某些属性设置为null的国家/地区之后吗如何在@PostMapping
期间正确访问此人所在的国家/地区,而无需采取变通办法,例如通过其ID明确获取该国家/地区?
该代码也可以在github上使用。它使用了h2database,但是hibernate和postgresql存在相同的问题。请注意,在启动过程中插入了两个国家/地区,因此当国家/地区ID设置为1或2时不会抛出任何违反外键的情况。
答案 0 :(得分:0)
您尝试添加
@ManyToOne(cascade = CascadeType.MERGE)
答案 1 :(得分:0)
如果您在有效负载中提供了country_id,则只能从存储库中获取国家/地区。然后将整个国家/地区对象设置为Person并保存person。