大家好,
我正在构建此Spring Rest API,目前在控制器上的put方法存在问题。
我有一个与测试实体有关系的问题实体:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="question_id", nullable = false, updatable = false)
private Long id;
@Column(name="question_text", nullable = false)
@NotNull
private String question;
@Column(name="question_weight", nullable = false)
@Min(1)
private Integer weight = 1;
@Column(name="question_type", nullable = false)
private String type = "radio";
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "last_modified", nullable = false)
@LastModifiedDate
private Date lastModified;
@ManyToOne(fetch = FetchType.LAZY, optional = false, targetEntity = com.QCMGenerator.QCMGenerator.Model.Test.class)
@JoinColumn(name = "test_id", referencedColumnName = "test_id", nullable = false, updatable = false)
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonIgnore
private Test test;
我早些时候发布了询问此问题的信息,并被告知要使用DTO,所以我这样做了,这是我的问题DTO:
private Long id;
private String question;
private String type;
private Integer weight;
private Date lastModified;
private TestDTO test;
这是我控制器中的put方法:
@PutMapping("/{questionID}")
public QuestionDTO updateQuestion(
@PathVariable(value = "testID") Long testID,
@PathVariable(value = "questionID") Long questionID,
@Valid @RequestBody QuestionDTO newQuestion
){
if(!testRepo.existsById(testID)){
throw new ResourceNotFoundException("No test with the ID '"+testID+"' was found...");
}
QuestionDTO savedDTO = null;
try {
Question questionEntity = questionRepo.findById(questionID).get();
QuestionDTO questionDTO = convertToDTO(questionEntity);
if (newQuestion.getTest() != null) {
questionDTO.setTest(newQuestion.getTest());
}
if (newQuestion.getQuestion() != null) {
questionDTO.setQuestion(newQuestion.getQuestion());
}
if (newQuestion.getType() != null) {
questionDTO.setType(newQuestion.getType());
}
if (newQuestion.getWeight() != null) {
questionDTO.setWeight(newQuestion.getWeight());
}
Question newQuestionEntity = convertToEntity(questionDTO);
Question saved = questionRepo.save(newQuestionEntity);
savedDTO = convertToDTO(saved);
}catch (Exception e){
System.out.println(e.getMessage());
}
return savedDTO;
}
并且我一直在我的IDE控制台上收到此错误:
2018-11-18 21:33:12.249警告12876-[nio-8080-exec-2] ohaiUnresolvedEntityInsertActions:HHH000437:尝试保存一个或多个具有不可空关联且未保存瞬态的实体实体。在保存这些从属实体之前,必须将未保存的临时实体保存在操作中。 未保存的临时实体:([com.QCMGenerator.QCMGenerator.Model.Test#]) 从属实体:([[com.QCMGenerator.QCMGenerator.Model.Question#10]]) 不可为空的关联:([com.QCMGenerator.QCMGenerator.Model.Question.test]) org.hibernate.TransientPropertyValueException:非null属性引用一个瞬态值-必须在当前操作之前保存瞬态实例:com.QCMGenerator.QCMGenerator.Model.Question.test-> com.QCMGenerator.QCMGenerator.Model.Test;嵌套异常是java.lang.IllegalStateException:org.hibernate.TransientPropertyValueException:非null属性引用一个瞬态值-必须在当前操作之前保存瞬态实例:com.QCMGenerator.QCMGenerator.Model.Question.test-> com.QCMGenerator。 QCMGenerator.Model.Test
我希望这里有人可以为我澄清这个问题,因为我整日都只停留在那种单一方法上,或者其他方法都可以正常工作,我尝试过使用DTO和不使用DTO,并且在添加之前我已经在某些字段上接受空值的方法存在问题。
我非常感谢您提供的任何帮助,并感谢大家的帮助。
大家都过得愉快。 :D
答案 0 :(得分:0)
当您尝试保存具有空ID的实体关联时,会发生此错误。
意思是这种情况下的convertToEntity
方法
Question newQuestionEntity = convertToEntity(questionDTO);
返回带有新Test
对象的问题实体。
您应该检查其ID为null时实体内部的所有关系是否为空。
答案 1 :(得分:0)
您需要在实体中添加ID,以便将具有该ID的实体保存为参考。
易于解决:
Question newQuestionEntity = convertToEntity(questionDTO);
newQuestionEntity.setId(testID);
最佳解决方案是:
questionDTO.setID(testID);
public Question convertToEntity(QuestionDTO qDto) {
Question question = new Question(qDto.getID()) ;
.......
return question;
}