使用 @OneToMany 和 @ManyToOne 注释是更新一个实体表,而不是许多表

Posted

技术标签:

【中文标题】使用 @OneToMany 和 @ManyToOne 注释是更新一个实体表,而不是许多表【英文标题】:Using @OneToMany and @ManyToOne annotations is updating one entity table but not the many table 【发布时间】:2020-07-18 15:08:26 【问题描述】:

我有一个 Spring RESTful API,它使用 H2 数据库和 JPA 来填充一些表。我正在尝试使用字段@OneToMany 设置一个实体,而另一个实体对象是@ManyToOne。当我在 Postman 中发出 POST 请求时,我 sout 我的 Quiz quiz 这是请求正文,字段与预期一致。然而,当我在 localhost 上登录数据库时,只有 quiz_table 更新为正确的属性。

当我发出 POST 请求时,我会在控制台中得到这个输出

Hibernate: insert into quiz_table (answer, text, title, id) values (?, ?, ?, ?)

我的 JSON 请求正文是


    "title": "Tottenham Quiz",
    "text": "When did Tottenham Hotspur last win a trophy?",
    "options": ["2002", "2019"],
    "answer": 1

服务器响应是


    "id": 67,
    "title": "Tottenham Quiz",
    "text": "When did Tottenham Hotspur last win a trophy?",
    "options": [
        
            "id": 0,
            "quiz": null,
            "option": "2002"
        ,
        
            "id": 0,
            "quiz": null,
            "option": "2019"
        
    ]

据我所知,"options" 的值正在传递给List<Option> 这是我的控制器与此端点的映射

 @PostMapping(path = "api/quizzes", produces = "application/json")
    public Quiz addQuiz(@Valid @RequestBody Quiz quiz) 
        quizRepository.save(quiz);
        return quiz;
    

Quiz


@Component
@Entity(name = "quiz_table")
public class Quiz 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @NotBlank(message = "Title must not be blank")
    private String title;

    @NotBlank(message = "Text must not be blank")
    private String text;

    @Size(min = 2)
//    @NotNull
    @OneToMany(mappedBy = "quiz")
    private List<Option> options;

    @JsonIgnore
    private int answer;

    public Quiz() 

    public Quiz(String title, String text, List<Option> options, int answer) 
        this.title = title;
        this.text = text;
        this.options = options;
        this.answer = answer;
    

Option

@Component
@Entity(name = "options_table")
public class Option 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @ManyToOne
    @JoinColumn
    private Quiz quiz;

    private String option;

    // for Jackson deserielization
    public Option() 
    

    /*public Option(Quiz quiz, String option) 
        this.quiz = quiz;
        this.option = option;

    */

    public Option(String option) 
        this.option = option;
    
    // getters/setters

编辑:实施建议后的异常 JSON 响应


    "id": 1,
    "title": "Tottenham Quiz",
    "text": "When did Tottenham Hotspur last win a trophy?",
    "options": [
        
            "id": 2,
            "quiz": 
                "id": 1,
                "title": "Tottenham Quiz",
                "text": "When did Tottenham Hotspur last win a trophy?",
                "options": [
                    
                        "id": 2,
                        "quiz": 
                            "id": 1,
                            "title": "Tottenham Quiz",
                            "text": "When did Tottenham Hotspur last win a trophy?",
                            "options": [
                                
                                    "id": 2,
                                    "quiz": 
                                        "id": 1,
                                        "title": "Tottenham Quiz",
                                        "text": "When did Tottenham Hotspur last win a trophy?",
                                        "options": [
                                            
                                                "id": 2,
                                                "quiz": 
                                                    "id": 1,
                                                    "title": "Tottenham Quiz",
                                                    "text": "When did Tottenham Hotspur last win a trophy?",
                                                    "options": [
                                                        
                                                            "id": 2,
                                                            "quiz": 
                                                                "id": 1,
                                                                "title": "Tottenham Quiz",
                                                                "text": "When did Tottenham Hotspur last win a trophy?",
                                                                "options": [
                                                                    
                                                                        "id": 2,
                                                                        "quiz": 
                                                                            "id": 1,
                                                                            "title": "Tottenham Quiz",
                                                                            "text": "When did Tottenham Hotspur last win a trophy?",
                                                                            "options": [
                                                                                
                                                                                    "id": 2,
                                                                                    "quiz": 
                                                                                        "id": 1,
                                                                                        "title": "Tottenham Quiz",
                                                                                        "text": "When did Tottenham Hotspur last win a trophy?",
                                                                                        "options": [
                                                                                            
                                                                                                "id": 2,
                                                                                                "quiz": 
                                                                                                    "id": 1,
                                                                                                    "title": "Tottenham Quiz",
                                                                                                    "text": "When did Tottenham Hotspur last win a trophy?",
                                                                                                    "options": [
                                                                                                        
                                                                                                            "id": 2,
                                                                                                            "quiz": 
                                                                                                                "id": 1,
                                                                                                                "title": "Tottenham Quiz",
                                                                                                                "text": "When did Tottenham Hotspur last win a trophy?",
                                                                                                                "options": [
                                                                                                                    
                                                                                                                        "id": 2,
                                                                                                                        "quiz": 
                                                                                                                            "id": 1,
                                                                                                                            "title": "Tottenham Quiz",
                                                                                                                            "text": "When did Tottenham Hotspur last win a trophy?",
                                                                                                                            "options": [
                                                                                                                                
                                                                                                                                    "id": 2,
                                                                                                                                    "quiz": 
                                                                                                                                        "id": 1,
                                                                                                                                        "title": "Tottenham Quiz",
                                                                                                                                        "text": "When did Tottenham Hotspur last win a trophy?",
                                                                                                                                        "options": [
                                                                                                                                            
                                                                                                                                                "id": 2,
                                                                                                                                                "quiz": 
                                                                                                                                                    "id": 1,
                                                                                                                                                    "title": "Tottenham Quiz",
                                                                                                                                                    "text": "When did Tottenham Hotspur last win a trophy?",
                                                                                                                                                    "options": [
                                                                                                                                                        
                                                                                                                                                            "id": 2,
                                                                                                                                                            "quiz": 
                                                                                                                                                                "id": 1,
                                                                                                                                                                "title": "Tottenham Quiz",
                                                                                                                                                                "text": "When did Tottenham Hotspur last win 
// ... continues for 4000 lines!

【问题讨论】:

您是否尝试添加级联选项?我认为这就是您无法保存子实体的原因。 我完全忽略了这一点。我猜没有默认设置? 【参考方案1】: 使用 JPA/Hibernate,您需要明确管理双向关系
    @PostMapping(path = "api/quizzes", produces = "application/json")
   public Quiz addQuiz(@Valid @RequestBody Quiz quiz) 
       quiz.getOptions().forEach(option -> option.setQuiz(quiz));
       quizRepository.save(quiz);
       return quiz;
   
另外,你必须告诉hibernate,当它管理Quiz,也级联Option
    @Size(min = 2)
    @OneToMany(mappedBy = "quiz", cascade = CascadeType.ALL)
    private List<Option> options;

【讨论】:

它成功了,谢谢。我完全监督,CascadeType 被教授,但我不明白它必须明确声明。我虽然得到了一个不寻常的 JSON 响应,但它似乎是在响应中递归地添加返回的测验。我将在主帖中发布一个 sn-p。 这不是休眠问题。那是杰克逊的问题。看到这个答案***.com/questions/62623483/… 如果遇到困难请告诉我

以上是关于使用 @OneToMany 和 @ManyToOne 注释是更新一个实体表,而不是许多表的主要内容,如果未能解决你的问题,请参考以下文章

EclipseLink 如何使用两个@OneToMany 和@ManyToOne 来替换@ManyToMany

使用 OnetoMany 和 ManytoOne 映射时的无限递归循环(双向)

@JoinFormula 和 @OneToMany 定义 - 糟糕的文档

在 Spring Boot 和 PostgreSQL 中使用 OneToMany 关系

无法使用 OneToMany 和 ManyToOne 关系在休眠中创建表(也无法创建外键)

JPA、OneToMany 和 ManyToOne