2

SpringBoot Version:1.4.2.RELEASE MySQL Version:5.7.16 Lombok

I have two entity classes Question and Options where question_id from Question table is foreign key in Question_Option table.

Question Entity

@Entity
@Table(name = "questions")
public class Question {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Getter
@Setter
private int questionId;
@Getter
@Setter
@OneToMany(mappedBy = "question",fetch=FetchType.LAZY,   cascade=CascadeType.ALL)
private List<Option> option;

Options Entity

@Entity
@Table(name = "questions_options")
public class Option {
@Id
@GeneratedValue
@Getter
@Setter
private int id;
@Getter
@Setter
private String optionsId;
@Getter
@Setter
 private String optionText;
@ManyToOne
@JoinColumn(name="questionId")
@Getter
@Setter
private Question question;
}

Problem Statement When I try to POST, foreign key (question_id) is not inserted in options table.

Hibernate: insert into questions (questionId, LastUpdate, active, createTime, questionText, questionType) values (default, ?, ?, ?, ?, ?)
Hibernate: insert into questions_options (id, lastUpdate, optionText, optionsId, questionId) values (default, ?, ?, ?, ?)
Hibernate: insert into questions_options (id, lastUpdate, optionText, optionsId, questionId) values (default, ?, ?, ?, ?)

Hibernate: insert into questions_options (id, lastUpdate, optionText, optionsId, questionId) values (default, ?, ?, ?, ?)

How did I fix this ? I changed Question entity to

@Getter
@Setter
@OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
@JoinColumn(name="questionId")
@NotNull
private List<Option> option;

and Options to

@ManyToOne
@Getter
@Setter
@JoinColumn(name="questionId")
private Question question;

But I want to know why first approach is not working and what am I doing wrong.

Deepu Nair
  • 165
  • 5
  • 15
  • http://stackoverflow.com/questions/11938253/jpa-joincolumn-vs-mappedby – Pallav Jha Jan 09 '17 at 07:16
  • Your 2nd approach may work but it is wrong. Revert it to the original mapping and ensure that you set both sides of the relationship before saving i.e. ensure you have called option.setQuestion(question); – Alan Hay Jan 09 '17 at 09:02
  • Alan is correct. Even with cascading (Cascading.ALL) the Option side still owns the relationships and the value of the foreign key is taken from Option's question member (that's specified by the mappedBy="question" on Question). – Michal Jan 09 '17 at 09:45
  • Thanks @Alan Hay and @ Michal . I changed the relation to unidirectional (by removing question relationship from options Entity )and it just worked. Coming back to my actual question, how do I make sure that option.setQuestion(question) is called ? I thought Cascade.ALL will take care of that. Is there any annotation to enforce it ? (Sorry I am a newbie :( ) – Deepu Nair Jan 09 '17 at 15:54
  • @Alan setting option.setquestion() throughs Cannot add or update a child row: a foreign key constraint fails – K Guru Oct 17 '18 at 10:58

2 Answers2

1

Try below relationship it should work.

Question Entity

@OneToMany(mappedBy = "question",fetch=FetchType.LAZY,cascade=CascadeType.ALL, targetEntity = Option.class)
private List<Option> option

Options Entity

@ManyToOne
@JoinColumn(name = "questionId")
private Question question;
Suman Behara
  • 150
  • 9
0

This is how it should be in the controller class.

@PostMapping("/question")
public question addQuestion(@RequestBody Question question) {

    if( question.getOption().size() > 0 )
    {
        question.getOption().stream().forEach( option -> {
            option.setQuestion( question );
        } );
    }

   // You can save this question object now using the repository instance autowired.
    return question;
}

One more thing, in the Option class entitiy, you need to add @JsonIgnore annotation as below to avoid recursive fetching

@ManyToOne
@Getter
@Setter
@JoinColumn(name="questionId")
@JsonIgnore
private Question question;
Udith Indrakantha
  • 860
  • 11
  • 17