我正在将 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.
我在这个问题上挣扎了一上午,所以我真的希望你们能提供帮助。抱歉我的英语不好
可能有更好的解决方案,但我会这样做: 在您的 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();
}