外键在一对多关系中始终为空 - Spring Boot Data with JPA
Posted
技术标签:
【中文标题】外键在一对多关系中始终为空 - Spring Boot Data with JPA【英文标题】:Foreign key is always null in one to many relation - Spring Boot Data with JPA 【发布时间】:2019-02-07 15:25:53 【问题描述】:我有两个实体类 Country
和 Language
具有双向一对多关系。
以下是实体类:
@Entity
@Table(name = "COUNTRY")
public class Country
@Id
@GeneratedValue
@Column(name = "COUNTRY_ID")
private Long id;
@Column(name = "COUNTRY_NAME")
private String name;
@Column(name = "COUNTRY_CODE")
private String code;
@JacksonXmlElementWrapper(localName = "languages")
@JacksonXmlProperty(localName = "languages")
@OneToMany(mappedBy = "country", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
List<Language> languages;
// getters and setters
还有……
@Entity
@Table(name = "LANGUAGE")
public class Language
@Id
@GeneratedValue
@Column(name = "LANGUAGE_ID")
private Long id;
@Column(name = "LANGUAGE_NAME")
private String name;
@ManyToOne
@JoinColumn(name = "COUNTRY_ID")
@JsonIgnore
private Country country;
//getters and setters
下面是我的 Rest 控制器:
@RestController
@RequestMapping("/countries")
public class CountryRestController
private final ICountryRepository iCountryRepository;
@Autowired
public CountryRestController(ICountryRepository iCountryRepository)
this.iCountryRepository = iCountryRepository;
@PostMapping("/country")
public ResponseEntity<?> postCountryDetails(@RequestBody Country country)
Country savedCountry = this.iCountryRepository.save(country);
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/id")
.buildAndExpand(savedCountry.getId()).toUri();
return ResponseEntity.created(location).build();
//other methods
我正在尝试保存以下 JSON:
"name": "Ireland",
"code": "IRE",
"languages": [
"name": "Irish"
]
问题在于语言(子)外键始终为空,但正在插入其他属性。我在Language
类的Country country
属性上使用了@JsonIgnore
,因为它会导致请求大小出现问题,因为我有另一个API 正在获取Country 及其语言的数据。
请指导。
【问题讨论】:
【参考方案1】:将Country
类中languages
的设置器更新为以下内容:
public void setLanguages(List<Language> languages)
this.languages = languages;
languages.forEach(entity -> entity.setCountry(this));
【讨论】:
【参考方案2】:你也可以这样做。 在这里它不会创建新对象。在解析的同一对象中,它在语言对象中创建关系。
@PostMapping("/country")
public Country postCountryDetails(@RequestBody Country country)
if( country.getLanguages().size() > 0 )
country.getLanguages().stream().forEach( countryItem ->
countryItem.setCountry( country );
);
return country;
【讨论】:
【参考方案3】:你可以这样做:
Country newCountry = new Country(country.getName());
ArrayList < Language > langList = new ArrayList<>();
for (Language lang : country.getLanguages())
langList.add( new Language(language.getName(), newCountry ) ) ;
newCountry.setLanguages( langList );
iCountryRepository.save(newCountry);
PS:不要忘记添加适当的构造函数。 此外,如果您要像这样进行构造函数重载,则必须添加默认构造函数:
public Country()
public Country(String name) this.name = name
【讨论】:
谢谢。它对我有用。你能给我一些解释你的答案吗?为什么它不符合我的方式? 我认为这是因为输入对象(国家)有孩子(语言),孩子不知道他们的父对象在 Hibernate 上下文中是谁。因此,您需要创建新的 Parent 和 child 并明确设置 child 的 parent。 这就是为什么当您最初按照自己的方式进行操作时,尽管没有外键,但它在两个表中都插入了..但是当您告诉上下文(使用构造函数)指向哪个 Parent 对象时,然后它首先在子表中插入父对象并映射外键。 如何仅使用域类来实现?没有两次创建对象?以上是关于外键在一对多关系中始终为空 - Spring Boot Data with JPA的主要内容,如果未能解决你的问题,请参考以下文章