简体   繁体   English

JPA一对多无需连接表

[英]JPA one to many without join table

I am trying to create JPA entity classes for quiz database where I have two entities Questions and Options. 我正在尝试为测验数据库创建JPA实体类,其中有两个实体“问题”和“选项”。

Approach 1 方法1

Create and OneToMany relation from Question to Option like this 像这样从问题到选项创建和OneToMany关系

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Option> options = new HashSet<>();

And ManyToOne relation created from options entity like this 从这样的选项实体创建的ManyToOne关系

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "questionId")
private Question question;

It worked fine except the fact that it created an extra table questions_options and question-option relations are managed in that table. 它创建了一个额外的表,但它在表中管理的问题和选项-关系之间的关系很好,但效果很好。 Also, Option has questionId column and its null for all the records. 另外,Option具有questionId列,并且所有记录的null。

I want to avoid that extra table and want to populated questionid in the options table.So after a little googling, I came to know that I need to use mappedBy attribute. 我想避免使用该多余的表,并希望在options表中填充questionid.so进行了一段时间的搜索之后,我知道我需要使用mapledBy属性。

Approach 2 方法2

Question Entity 问题实体

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy="question")
private Set<Option> options = new HashSet<>();

Option Entity 期权实体

@ManyToOne(fetch = FetchType.LAZY)
private Question question;

Now Join table is not created, instead question_questionId column is added to Options table but again it coming as null . 现在未创建Join表,而是将question_questionId列添加到Options表中,但再次将其作为null出现。 Because of this my endpoint is not returning options with the question. 因此,我的端点不返回带有问题的选项。

I hope my question is clear. 希望我的问题清楚。 How to populate questionId in Options table. 如何在“选项”表中填充questionId。

EDIT 编辑

Full Question entity 完整问题实体

@Entity
@Table(name="questions")
public class Question implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int questionId;

    private String author;

    private boolean expired;

    private String questionText;

    //bi-directional many-to-one association to Option
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy="question")
    private Set<Option> options = new HashSet<>();

    public Question() {
    }

    public int getQuestionId() {
        return this.questionId;
    }

    public void setQuestionId(int questionId) {
        this.questionId = questionId;
    }

    public String getAuthor() {
        return this.author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public boolean isExpired() {
        return expired;
    }

    public void setExpired(boolean expired) {
        this.expired = expired;
    }

    public String getQuestionText() {
        return this.questionText;
    }

    public void setQuestionText(String questionText) {
        this.questionText = questionText;
    }

    public Set<Option> getOptions() {
        return this.options;
    }

    public void setOptions(Set<Option> options) {
        this.options = options;
    }

    public Option addOption(Option option) {
        getOptions().add(option);
        option.setQuestion(this);

        return option;
    }

    public Option removeOption(Option option) {
        getOptions().remove(option);
        option.setQuestion(null);

        return option;
    }

}

Option Entity @Entity @Table(name="options") public class Option implements Serializable { private static final long serialVersionUID = 1L; 选项实体@Entity @Table(name =“ options”)公共类选项实现​​Serializable {private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int optionId;

private boolean correctAnswer;

private String optionText;

//bi-directional many-to-one association to Question
@ManyToOne(fetch = FetchType.LAZY)
private Question question;

public Option() {
}

public int getOptionId() {
    return this.optionId;
}

public void setOptionId(int optionId) {
    this.optionId = optionId;
}

public boolean isCorrectAnswer() {
    return correctAnswer;
}

public void setCorrectAnswer(boolean correctAnswer) {
    this.correctAnswer = correctAnswer;
}

public String getOptionText() {
    return this.optionText;
}

public void setOptionText(String optionText) {
    this.optionText = optionText;
}

public Question getQuestion() {
    return this.question;
}

public void setQuestion(Question question) {
    this.question = question;
}

} }

Repository 知识库

@Repository
public interface QuestionRepository extends CrudRepository<Question,Long>{

}

Service Class 服务等级

@Autowired
    private QuestionRepository questionRepository;
    public Question getQuestion(Long id) {
        Question  question= questionRepository.findOne(id);
        Set<Option> options = question.getOptions();
        options.forEach(s -> s.setCorrectAnswer(false));
        return question;
    }

    public Question addQuestion(Question question) {
        return questionRepository.save(question);
    }

Controller 调节器

@GetMapping
    @RequestMapping(method = RequestMethod.GET, value="/questions/{id}")
    public ResponseEntity<Question> getQuestion(@PathVariable long id) {
        return new ResponseEntity<Question>(questionService.getQuestion(id),HttpStatus.OK);
    }

    @PostMapping
    @RequestMapping(method = RequestMethod.POST, value= "/questions")
    @Transactional
    public ResponseEntity<Question> addQuestion(@RequestBody Question question) {
        logger.info("Request recieved from client : " + question.toString());
        return new ResponseEntity<Question>(questionService.addQuestion(question),HttpStatus.OK);
    }

在此处输入图片说明

在此处输入图片说明

I think your addQuestion method should look like this: 我认为您的addQuestion方法应如下所示:

public Question addQuestion(Question question) {
   Question newQuestion = questionRepository.save(question);
   question.getQuestions().forEach(option -> {
      Option newOption = new Option();
      newOption.setQuestion(newQuestion); // need to reference managed (attached to JPA session) entity
      newOption.setOptionText(option.getOptionText());
      newOption.setCorrectAnswer(Optional.ofNullable(option.isCorrectAnswer()).orElse(false)));
      newQuestion.getOptions().add(optionRepository.save(newOption));
   });

   // it's done implicitly here because your controller's (or service's) method 
   // is marked with @Transactional, otherwise it must be done explicitly
   // newQuestion = questionRepository.save(newQuestion);

   return newQuestion;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM