繁体   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