【问题标题】:Foreign key is always null in one to many relation - Spring Boot Data with JPA外键在一对多关系中始终为空 - Spring Boot Data with JPA
【发布时间】:2019-02-07 15:25:53
【问题描述】:

我有两个实体类 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"
    }
  ]
}

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

请指导。

【问题讨论】:

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


    【解决方案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 对象时,然后它首先在子表中插入父对象并映射外键。
        • 如何仅使用域类来实现?没有两次创建对象?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-09-23
        • 2021-09-27
        • 2021-05-23
        • 2018-04-14
        • 2022-11-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多