ModelMapper在运行JpaRepository的Save方法时映射错误的Id

问题描述 投票:0回答:1

我正在将 Hibernate 用于我的 Spring Boot 项目。所以我在使用 JpaRepository 的 Save 方法时遇到问题。当我尝试保存一个新项目

Answer
时,ModelMapper 错误地认为
Answer
的属性是
questionId
作为
answerId
对象的
Answer
,因此不是保存新的
Answer
项目,而是使用我输入的
Answer
更新现有的
answerId = questionId
项目。

这是我的答案和问题模型:

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class Answer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int answerId;
    private String answer;
    private String status;

    @ManyToOne()
    @JoinColumn(name = "questionId", nullable = false)
    private Question question;
}
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class Question {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int questionId;
    private String question;
    private String questionType;
    private String status;

    @ManyToMany(mappedBy = "questions", cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    private Set<Quiz> quizzes;

    @OneToMany(mappedBy = "question",cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Answer> answers;
}

我的DTO

public class AnswerDTO {

    @NotEmpty
    private String answer;

    @NotEmpty
    private String status;

    @NotNull
    private Integer questionId;


}

我的模型映射器

@Configuration
public class Config {

    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();

        // ignore null attributes on the source object on copying
        modelMapper.getConfiguration()
                .setSkipNullEnabled(true);      
        return modelMapper;
    }
}

答案生成器:

@Component
@AllArgsConstructor
public class AnswerBuilder {

    private final ModelMapper modelMapper;
    public Answer build(AnswerDTO dto) {
        Answer model = modelMapper.map(dto, Answer.class);
        return model;
    }

    public Optional<AnswerDTO> build(Answer domain) {
        AnswerDTO dto = modelMapper.map(domain, AnswerDTO.class);
        return Optional.of(dto);
    }

    public Answer build(AnswerDTO dto, Answer domain) {
        modelMapper.map(dto, domain);
        return domain;
    }
}

这是我创建的服务:

public int createNewAnswer(AnswerDTO dto) {
        return Stream.of(dto)
                .map(answerBuilder::build)
                .map(answerRepository::save)
                .map(Answer::getAnswerId)
                .findFirst()
                .get();
    }

我尝试对 ModelMapper 使用 setMatchingStrategy(MatchingStrategies.STRICT) 但答案列表中的所有 QuestionId 都变为 null。而且我无法保存新项目。错误如下:

com.microsoft.sqlserver.jdbc.SQLServerException: Cannot insert the value NULL into column 'question_id', table 'SPRINGTEST.dbo.answer'; column does not allow nulls.

我在这个问题上挣扎了一上午,所以我真的希望你们能提供帮助。抱歉我的英语不好

java spring-boot hibernate jpa modelmapper
1个回答
0
投票

可能有更好的解决方案,但我会这样做: 在您的 AnswerBuilder 中:

//create an id constructor for Question if you're going for option 2
public class Question {
  Question(long id){
    this.id = id
  }
  // rest of code...
}

@Component
@AllArgsConstructor
public class AnswerBuilder {
    private final QuestionRepository questionRepository; //inject the repo if you're going for option 1
    private final ModelMapper modelMapper;
    public Answer build(AnswerDTO dto) {
      Answer model = modelMapper.map(dto, Answer.class);
      // option 1:
      questionRepository.findById(dto.getQuestionId())
        .ifPresent(question -> model.setQuestion(question));

      //option 2:
      model.setQuestion(new Question(dto.getQuestionId()));
      return model;
    }
    // rest of code...
}

你不必总是使用函数式编程“方式”

public int createNewAnswer(AnswerDTO dto) {
  return Stream.of(dto)
          .map(answerBuilder::build)
          .map(answerRepository::save)
          .map(Answer::getAnswerId)
          .findFirst()
          .get();
}

有些代码可以命令式完成,更加简洁。

public int createNewAnswer(AnswerDTO dto) {
  Answer answer = answerBuilder.build(dto);
  return answerRepository.save(answer).getAnswerId();
}
© www.soinside.com 2019 - 2024. All rights reserved.