带有输入请求的春季输入验证

时间:2018-11-18 20:40:54

标签: spring hibernate rest spring-boot put

大家好,

我正在构建此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

2 个答案:

答案 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;
}