当前位置: 首页 > 知识库问答 >
问题:

Thymeleaf Spring Boot,带ArrayList的动态字段

厍光霁
2023-03-14

我使用Spring Boot和百里香叶,并尝试使用表单设置列表元素(即对象)。更准确地说,我有两个实体:聚合答案列表的问题,我将问题对象传递给模型,并尝试在迭代中设置每个答案对象。当按下保存(提交表格)时,我得到异常:

字段“答案”上对象“问题”中的字段错误:拒绝值[[答案(id=0,答案编号=1,文本=,正确=假),答案(id=0,答案编号=2,文本=,正确=假),答案(id=0,答案编号=3,文本=,正确=假),答案(id=0,答案编号=4,文本=,正确=假)]];代码[typeMismatch.question.answers,typeMismatch.answers,typeMismatch.java.util.List,类型不匹配];参数[org.springframework.context.support.DefaultMessageSourceResolvable:代码[question.answers,答案];参数[];默认消息[答案]];默认消息[未能将类型“java.lang.String”的属性值转换为属性“答案”所需的类型“java.util.List”;嵌套异常java.lang.IllegalStateException:无法将类型“java.lang.String”的值转换为属性“答案[0]”所需的类型“com.easetest.website.model.Answer”:没有匹配的编辑器或找到转换策略]]

我的控制器类问题方法

@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;
    }
}

有谁知道是什么原因导致这个错误,我该如何解决它?

共有1个答案

丘向荣
2023-03-14

错误消息中最重要的消息是:无法将类型为“java.lang.字符串”的值转换为所需的类型“com.easetest.网站.model.Answer”。为了解决这个问题,我不得不:

>

  • 创建实现converter的转换器

    在WebConfig中添加该转换器

    实现如下:

    转换器类:

    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类

    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());
        }
    }
    

    希望它对某人有用。

  •  类似资料:
    • 问题内容: 我的数据如下所示: 我给我一个字符串列表作为 但是,当我传递给时,它仅返回带有的数据,这是列表中的第一个元素。 我想知道是否有人对此有何想法?任何帮助,将不胜感激! 问题答案: 由于我相信R DBI驱动程序尚未实现多个SQL语句支持,因此仅返回第一条语句。 因此,您需要为多个SQL语句迭代运行 sqlcmd ,例如使用with返回数据帧列表,然后调用单个主数据帧: 或者,对一个SQL语

    • 我对编码还是很陌生,所以我只是在尝试制作一些简单的游戏,比如Snake。现在,我正试图让苹果被吃掉时的轨迹沿着头部,但我遇到了一个问题。 我现在有它,这样尾巴在正确的时间在正确的地方产卵,但它们不会移动。它们产卵并静止。我的尾部片段存储在ArrayList中,我不知道如何在每个滴答声中更新矩形的坐标值。如何更改每个矩形的坐标值? 这就是我目前所拥有的。这是我的蛇类的一部分,它会产生尾巴并绘制它们

    • 问题内容: 我正在尝试克服Rails中动态表单字段的障碍- 这似乎是框架无法很好地处理的。我也在我的项目中使用jQuery。我已经安装了jRails,但是我更愿意在可能的情况下毫不干扰地编写AJAX代码。 我的表单相当复杂,嵌套的两个或三个级别并不罕见。我遇到的问题是生成正确的表单ID,因为它们是如此依赖于表单构建器上下文。我需要能够动态添加新字段或删除关系中的现有记录,而我完全不知所措。 到目前

    • 这是我唯一的代码:

    • 首选框架是Spring Web Service,但也欢迎其他解决方案。 问候,

    • 问题内容: 我有抽象类Human,这是另外两个类Student和Worker的延伸。我正在尝试填写两个数组列表。类型为Student的ArrayList和类型为Worker的ArrayList动态。 } } } } 问题答案: 当然,只需添加学生: 您可以为工人做几乎完全相同的事情。如果要使用循环,请执行以下操作: 这将创建一个新学生列表,其姓名后面有不同的编号。但是,如果您需要其他数据,则该数据