在多人关系的测验中添加问题

ybzsozfc  于 2021-06-26  发布在  Java
关注(0)|答案(2)|浏览(319)

我有一个 Many-To-Many relationship 介于 Quiz 表和a Question table。我想问的是,我是如何得到逻辑下来,能够添加一个问题到一个测验的测验id,所以我可以链接到一个特定的测验多个问题。
测验实体侧

  1. @ManyToMany(fetch = FetchType.EAGER, cascade = {
  2. CascadeType.MERGE
  3. })
  4. @JoinTable(name = "quiz_content",
  5. joinColumns = @JoinColumn(name = "quiz_id"),
  6. inverseJoinColumns = @JoinColumn(name = "question_id")
  7. )
  8. private List<Question> questions = new ArrayList<>();

问题实体方

  1. @ManyToMany(mappedBy = "questions")
  2. private List<Quiz> quizList = new ArrayList<>();

这是我的控制器:

  1. @PostMapping(value = "/add")
  2. public String addQuestionToQuiz(Quiz quiz, BindingResult bindingResult, Model model) {
  3. return "quiz/index";
  4. }

我如何在注解中实现逻辑,因为当我实现时,它会抛出如下错误:

  1. invalid property of bean class cannot get element with index 0 from set of size 0, accessed using property path.
qhhrdooz

qhhrdooz1#

你应该使用 Set 而不是 List . 在这种情况下不应该使用级联。我在下面添加了一个带有测试类的实现,您可以在其中看到如何添加 Question 示例到 Quiz 示例。
问题类

  1. package no.mycompany.myapp.misc;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. import javax.persistence.Entity;
  5. import javax.persistence.GeneratedValue;
  6. import javax.persistence.Id;
  7. import javax.persistence.ManyToMany;
  8. import java.util.HashSet;
  9. import java.util.Set;
  10. @Entity
  11. @Getter
  12. @Setter
  13. public class Question {
  14. @Id
  15. @GeneratedValue
  16. private long id;
  17. @ManyToMany(mappedBy = "questions")
  18. private Set<Quiz> quizList = new HashSet<>();
  19. }

问题VM类

  1. package no.mycompany.myapp.misc;
  2. import lombok.Getter;
  3. import lombok.NoArgsConstructor;
  4. import lombok.Setter;
  5. @Getter
  6. @Setter
  7. @NoArgsConstructor
  8. public class QuestionVM {
  9. private long id;
  10. // TODO add remaining fields except for collections containing Quiz instances
  11. public QuestionVM(Question question) {
  12. this.id = question.getId();
  13. // TODO init remaining fields
  14. }
  15. }

问题报告

  1. package no.mycompany.myapp.misc;
  2. import org.springframework.data.jpa.repository.JpaRepository;
  3. public interface QuestionRepo extends JpaRepository<Question, Long> { }

测验课

  1. package no.mycompany.myapp.misc;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. import javax.persistence.*;
  5. import java.util.HashSet;
  6. import java.util.Set;
  7. @Getter
  8. @Setter
  9. @Entity
  10. public class Quiz {
  11. @Id
  12. @GeneratedValue
  13. private long id;
  14. @ManyToMany(fetch = FetchType.EAGER)
  15. @JoinTable(name = "quiz_content",
  16. joinColumns = @JoinColumn(name = "quiz_id"),
  17. inverseJoinColumns = @JoinColumn(name = "question_id")
  18. )
  19. private Set<Question> questions = new HashSet<>();
  20. public void addQuestion(Question question) {
  21. question.getQuizList().add(this);
  22. questions.add(question);
  23. }
  24. public void removeQuestion(Question question) {
  25. question.getQuizList().remove(this);
  26. questions.remove(question);
  27. }
  28. }

快进班

  1. package no.mycompany.myapp.misc;
  2. import lombok.Getter;
  3. import lombok.NoArgsConstructor;
  4. import lombok.Setter;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import java.util.stream.Collectors;
  8. @Getter
  9. @Setter
  10. @NoArgsConstructor
  11. public class QuizVM {
  12. private long id;
  13. private List<QuestionVM> questions = new ArrayList<>();
  14. // TODO add remaining fields
  15. public QuizVM(Quiz quiz) {
  16. this.id = quiz.getId();
  17. this.questions = quiz.getQuestions().stream().map(QuestionVM::new).collect(Collectors.toList());
  18. // TODO init remaining fields
  19. }
  20. }

奎兹雷波

  1. package no.mycompany.myapp.misc;
  2. import org.springframework.data.jpa.repository.JpaRepository;
  3. public interface QuizRepo extends JpaRepository<Quiz, Long> { }

奎兹雷波试验

  1. package no.mycompany.myapp.misc;
  2. import org.junit.jupiter.api.Test;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
  5. import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
  6. import org.springframework.test.context.ActiveProfiles;
  7. import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
  8. @ActiveProfiles("test")
  9. @DataJpaTest
  10. public class QuizRepoTest {
  11. @Autowired
  12. TestEntityManager testEntityManager;
  13. @Autowired
  14. QuizRepo quizRepo;
  15. @Autowired
  16. QuestionRepo questionRepo;
  17. @Test
  18. public void test() {
  19. var quizInDb = new Quiz();
  20. var question1InDb = questionRepo.save(new Question());
  21. var question2InDb = questionRepo.save(new Question());
  22. quizInDb.addQuestion(question1InDb);
  23. quizInDb.addQuestion(question2InDb);
  24. quizInDb = quizRepo.save(quizInDb);
  25. // verify that Quiz instance has 2 questions
  26. var quiz = testEntityManager.find(Quiz.class, quizInDb.getId());
  27. assertThat(quiz.getQuestions().size()).isEqualTo(2);
  28. // verify that question #1 has 1 Quiz instance
  29. var question1 = testEntityManager.find(Question.class, question1InDb.getId());
  30. assertThat(question1.getQuizList().size()).isEqualTo(1);
  31. // remove question #1 from Quiz instance
  32. quizInDb = quizRepo.getOne(quiz.getId());
  33. question1InDb = questionRepo.getOne(question1.getId());
  34. quizInDb.removeQuestion(question1InDb);
  35. quizRepo.save(quizInDb);
  36. // verify that Quiz instance has 1 question
  37. quiz = testEntityManager.find(Quiz.class, quiz.getId());
  38. assertThat(quiz.getQuestions().size()).isEqualTo(1);
  39. // verify that question #1 has 0 Quiz instances
  40. question1 = testEntityManager.find(Question.class, question1InDb.getId());
  41. assertThat(question1.getQuizList().size()).isEqualTo(0);
  42. questionRepo.delete(question1InDb);
  43. // verify that question #1 is deleted from db
  44. assertThat(testEntityManager.find(Question.class, question1InDb.getId())).isNull();
  45. quizInDb = quizRepo.getOne(quiz.getId());
  46. question2InDb = quizInDb.getQuestions().stream().findFirst().orElse(null);
  47. question2InDb.setComment("test");
  48. quizRepo.save(quizInDb);
  49. var question2 = testEntityManager.find(Question.class, question2InDb.getId());
  50. assertThat(question2.getComment()).isEqualTo("test");
  51. }
  52. }

quizservice类

  1. import lombok.RequiredArgsConstructor;
  2. import org.springframework.stereotype.Service;
  3. import java.util.stream.Collectors;
  4. @Service
  5. @RequiredArgsConstructor
  6. public class QuizService {
  7. private final QuizRepo quizRepo;
  8. private final QuestionRepo questionRepo;
  9. public void saveQuiz(QuizVM quiz) {
  10. var quizInDb = quiz.getId() > 0 ? quizRepo.getOne(quiz.getId()) : new Quiz();
  11. // TODO: Copy updated fields from QuizVM instance to quizInDb
  12. // remove deleted questions
  13. quizInDb.getQuestions().removeAll(
  14. quizInDb.getQuestions().stream()
  15. .filter(questionInDb -> quiz.getQuestions().stream().noneMatch(it -> questionInDb.getId() == it.getId()))
  16. .collect(Collectors.toSet()));
  17. quiz.getQuestions().forEach(questionVM -> {
  18. var currentQuestionInDb = quizInDb.getQuestions()
  19. .stream()
  20. .filter(it -> it.getId() == questionVM.getId())
  21. .findFirst()
  22. .orElse(new Question());
  23. // TODO: Copy updated fields from QuestionVM instance to currentQuestion
  24. if (currentQuestionInDb.getId() < 1) {
  25. questionRepo.save(currentQuestionInDb);
  26. quizInDb.addQuestion(currentQuestionInDb);
  27. }
  28. });
  29. quizRepo.save(quizInDb);
  30. }
  31. }

控制器方法

  1. @PostMapping(value = "/add")
  2. public String addQuestionToQuiz(QuizVM quiz, BindingResult bindingResult, Model model) {
  3. return "quiz/index";
  4. }
展开查看全部
umuewwlo

umuewwlo2#

这是一种双向关系,因此需要使用自定义方法处理添加或删除操作,以避免任何不可预知的错误。您应该添加一个自定义 addQuestion() 方法,即 Quiz 实体。

  1. @Entity
  2. public class Quiz {
  3. //...
  4. public void addQuestion(Question question) {
  5. questions.add(question);
  6. question.getQuizList().add(this);
  7. }
  8. //...
  9. }

然后你可以在测验中添加一个问题:

  1. Question question = new Question();
  2. questionRepository.save(question);
  3. Quiz quiz = quizRepository.findById(quizId).get();
  4. quiz.addQuestion(question);
  5. quizRepository.save(quiz);

ps:我建议你使用 Set 而不是 List@ManyToMany 为了更好的表现。

展开查看全部

相关问题