外键在一对多关系中始终为空-使用JPA的Spring Boot Data

时间:2018-09-02 07:55:45

标签: json rest spring-boot spring-data-jpa one-to-many

我有两个实体类CountryLanguage具有双向一对多关系。

下面是实体类:

@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"
    }
  ]
}

问题在于,语言(子级)外键始终为null,但是正在插入其他属性。我在@JsonIgnore类的属性Country country上使用了Language,因为它引起请求大小的问题,因为我还有另一个API会提取Country的数据及其语言。

请指导。

3 个答案:

答案 0 :(得分:1)

您可以通过以下方式进行操作:

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 } 

答案 1 :(得分:1)

您也可以通过这种方式进行操作。 在这里它不会创建新对象。在解析的同一对象中,它在语言对象中创建关系。

@PostMapping("/country")
public Country postCountryDetails(@RequestBody Country country) {

    if( country.getLanguages().size() > 0 )
    {
        country.getLanguages().stream().forEach( countryItem -> {
            countryItem.setCountry( country );
        } );
    }
    return country;
}

答案 2 :(得分:0)

languages类中Country的设置器更新为以下内容:

 public void setLanguages(List<Language> languages) {
        this.languages = languages;
        languages.forEach(entity -> entity.setCountry(this));
    }