簡體   English   中英

Thymeleaf + Spring 啟動,動態字段與 ArrayList

[英]Thymeleaf + Spring Boot, dynamic fields with ArrayList

我正在使用 Spring 引導和 Thymeleaf 並嘗試使用表單設置列表的元素(即對象)。 更准確地說,我有 2 個實體: 匯總答案列表的問題,我將問題 object 傳遞給 model 並嘗試在迭代中設置每個答案 object。 按保存(提交表單)時出現異常:

object 字段“答案”上的“問題”中的字段錯誤:拒絕值 [[Answer(id=0, answerNumber=1, text=, correct=false), Answer(id=0, answerNumber=2, text=, correct=假),答案(id=0,答案號=3,文本=,正確=假),答案(id=0,答案號=4,文本=,正確=假)]]; 代碼 [typeMismatch.question.answers,typeMismatch.answers,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable:代碼 [question.answers,answers]; arguments []; 默認消息[答案]]; 默認消息 [無法將類型“java.lang.String”的屬性值轉換為屬性“answers”所需的類型“java.util.List”; 嵌套異常是 java.lang.IllegalStateException:無法將類型“java.lang.String”的值轉換為所需類型“com.easetest.website.model.Answer”屬性“answers[0]”:沒有匹配的編輯器或轉換策略成立]]

我的 Controller class 問題方法

@PostMapping("/editQuestion")
public String editQuestion(Model model, @RequestParam("test_id") int id, @RequestParam(value = "question_id", required = false) Integer question_id) {
    Test test = testService.getById(id);
    List<Question> questions = test.getQuestions();
    System.out.println(questions);
    int realNumberOfQuestion = questions.size(); // mozliwe ze nie potrzebne
    test.setMultipleAnswers(false);
    Question q = question_id == null ? null : questionService.getById(question_id);
    if(q == null) {
        q = new Question();
        if(realNumberOfQuestion < 1) {
            q.setQuestionNumber(1);
        } else if(questions.get(realNumberOfQuestion - 1).getQuestionBody().isEmpty()){
            q = questions.get(realNumberOfQuestion - 1);
        } else {
            q.setQuestionNumber(realNumberOfQuestion);
        }
    }

    model.addAttribute("test", test);
    model.addAttribute("question", q);
    System.out.println(q);

    return "business/question_form";
}

@PostMapping("/saveQuestion")
public String saveQuestion(Model model, @ModelAttribute("question") Question question, @RequestParam("test_id") int id) {
    System.out.println("Lubu dubu");
    Test test = testService.getById(id);
    test.setQuestion(question);
    testService.save(test);
    model.addAttribute("test", test);
    model.addAttribute("question", question);
    return "business/question_form";
}

問題表

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <!--Bootstrap dependencies-->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
          integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
            integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
            crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
            integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
            crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"
            integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI"
            crossorigin="anonymous"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    
    <script th:unless="${test.multipleAnswers}">
        $(document).on('click', 'input[type="checkbox"]', function () {
            $('input[type="checkbox"]').not(this).prop('checked', false);
        });
    </script>


    <meta charset="UTF-8">
    <title>Create Question</title>
</head>
<body class="mb-2 bg-secondary text-white">
<div class="container">
    <div>
        <h2 th:text="${test.testName}"></h2>

    </div>
    <div class="form-group">
        <h4>Add question</h4>
        <form action="#" th:action="@{/business/saveQuestion}" th:object="${question}" method="post">
            <div class="form-group">
                <input type="hidden" th:field="*{id}">
                <input type="hidden" th:field="*{answers}">
                <input type="hidden" th:name="test_id" th:value="${test.id}">
                <div class="form-group">
                    <label for="exampleFormControlTextarea1">Question body</label>
                    <textarea class="form-control" id="exampleFormControlTextarea1"
                              th:value="${question.questionBody}" rows="3"></textarea>
                </div>
                <br>

                <div th:each="answer, itemStat : *{answers}">
                    <div class="input-group mb-3">
                        <div class="input-group-prepend">
                            <div class="input-group-text">
                                <input type="hidden" th:field="*{answers[__${itemStat.index}__].id}">
                                <input type="hidden" th:field="*{answers[__${itemStat.index}__].answerNumber}">
                                <input type="checkbox" th:field="*{answers[__${itemStat.index}__].correct}">
                            </div>
                        </div>
                        <input type="text" class="form-control" th:field="*{answers[__${itemStat.index}__].text}">
                    </div>
                </div>
            </div>
            <br>
            <input type="submit" th:value="Save" class="btn btn-info">
        </form>
    </div>
    <ul class="pagination">
        <th:block th:each="question: ${test.questions}">
            <form method="post" action="#" th:action="@{/business/editQuestion}">
                <input type="hidden" th:name="test_id" th:value="${test.id}">
                <input type="hidden" th:name="question_id" th:value="${question.id}">
                <input type="submit" class="btn btn-danger" th:value=${question.questionNumber}>
            </form>
        </th:block>
        <form method="post" action="#" th:action="@{/business/addQuestion}">
            <input type="hidden" th:name="test_id" th:value="${test.id}">
            <input type="hidden" th:name="question_id" th:value="${question.id}">
            <input type="submit" class="btn btn-success" value="New Question">
        </form>
    </ul>
</div>
</body>
</html>

問題實體

@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Question {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="native")
    @GenericGenerator(name = "native", strategy = "native")
    private int id;

    @EqualsAndHashCode.Exclude
    private int questionNumber;

    @EqualsAndHashCode.Exclude
    private String questionBody = "";

    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @ManyToOne
    @JoinColumn(name = "test_id", nullable = false)
    private Test test;

    @EqualsAndHashCode.Exclude
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "question", orphanRemoval = true)
    private List<Answer> answers = Arrays.asList(
            new Answer(1, "", false),
            new Answer(2, "", false),
            new Answer(3, "", false),
            new Answer(4, "", false));

    public Question(int questionNumber) {
        this.questionNumber = questionNumber;
    }

    public void setAnswer(Integer num, String answer, boolean correct) {
        System.out.println(answers);
        if(answers == null) {
            answers = new ArrayList<>();
        }
        Answer a = answers.get(num - 1) != null ? answers.get(num - 1) : new Answer();
        a.setAnswerNumber(num);
        a.setText(answer);
        a.setCorrect(correct);
        a.setQuestion(this);
        answers.set(num-1, a);
    }

    public void removeAnswer(Integer num) {
        if(answers == null) {
            return;
        }
        answers.set(num-1, new Answer(num, "", false));
        }
    }

回答實體

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Answer {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="native")
    @GenericGenerator(name = "native", strategy = "native")
    private int id;
    @EqualsAndHashCode.Exclude
    private int answerNumber;
    @EqualsAndHashCode.Exclude
    private String text;
    @EqualsAndHashCode.Exclude
    private boolean correct;

    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @ManyToOne
    @JoinColumn(name = "question_id")
    private Question question;`enter code here`

    public Answer(int answerNumber, String text, boolean correct) {
        this.answerNumber = answerNumber;
        this.text = text;
        this.correct = correct;
    }
}

有誰知道導致該錯誤的原因以及我該如何解決?

找到解決方案。

錯誤消息中最重要的消息是: Cannot convert value of type 'java.lang.String' to required type 'com.easetest.website.model.Answer' 為了解決這個問題,我必須:

  • 創建實現 Converter<String, Answer> 的轉換器

  • 在 WebConfig 中添加該轉換器

下面的實現:

轉換器 class:

import com.easetest.website.model.Answer;
import lombok.RequiredArgsConstructor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class StringToAnswerConverter implements Converter<String, Answer> {

    @Override
    public Answer convert(String s) {
        String[] data = s.split(",");
        return new Answer(
                Integer.parseInt(getSubstringAfterChar(data[1], '=')),
                new String(getSubstringAfterChar(data[2], '=')),
                Boolean.parseBoolean(getSubstringAfterChar(data[3], '=')));
    }

    private String getSubstringAfterChar(String text, char character) {
        return text.substring(text.lastIndexOf(character) + 1);
    }
}

WebConfig class

import com.easetest.website.converters.StringToAnswerConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new StringToAnswerConverter());
    }
}

希望它對某人有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM