Thymeleaf视图不会将实体ID传递给Spring @Controller,而是将其与其他属性一起传递

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Thymeleaf视图不会将实体ID传递给Spring @Controller,而是将其与其他属性一起传递相关的知识,希望对你有一定的参考价值。

当我转到/add端点时,我的Controller会创建一个Contact对象并为其生成一个ID。然后将此ID正确传递到Thymeleaf视图并显示在网页上。当视图中的表单(使用POST)提交到Controller中的另一个端点时,除了ID字段之外,所有属性都会被传递。我使用Spring Model和@ModelAttribute注释将对象传入和传出视图。使用Lombok生成实体的getter和setter。

控制器类:

@Controller
public class PhonebookController {

    private final PhonebookService phonebookService;

    @Autowired
    public PhonebookController(PhonebookService phonebookService) {
        this.phonebookService = phonebookService;
    }

    @GetMapping("/add")
    public String addContact(Model model) {
        model.addAttribute("contact", new Contact(EntityUtils.generateId()));
        return "contact";
    }

    @PostMapping("/save")
    public String validateAndSaveContact(@ModelAttribute("contact") @Valid Contact contact, BindingResult bindingResult) { // contact.getId() returns null
        if (bindingResult.hasErrors()) {
            return "contact";
        }
        phonebookService.getContactRepository().save(contact);
        return "redirect:/contacts";
    }
}

实体类:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "contact")
public class Contact implements Comparable<Contact> {

    @Id
    private String id;
    @NotEmpty(message = "Name can not be empty.")
    private String name;
    @NotEmpty(message = "Number can not be empty.")
    @Pattern(regexp = "[0-9]+", message = "Number can contains only numbers.")
    private String number;

    public Contact(String id) {
        this.id = id;
    }

    @Override
    public int compareTo(Contact o) {
        return this.getName().compareTo(o.name);
    }
}

Thymeaf Viev:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Getting Started: Serving Web Content</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" href="/webjars/bootstrap/css/bootstrap.min.css"/>
    <script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
    <script type="text/javascript" src="/webjars/bootstrap/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/webjars/font-awesome/css/font-awesome.min.css"/>
</head>
<body>

    <div class="container">
        <div class="row">
            <div class="col-12">
                <h1>Add new contact</h1>
                <form th:action="@{/save}" method="post" th:object="${contact}">
                    <div class="form-group">
                        <label for="idText">Identifier (automaticaly generated):</label>
                        <strong id="idText" th:text="${contact.getId()}"></strong>
                    </div>
                    <div class="form-group">
                        <label for="nameInput">Contact name:</label>
                        <input type="text" th:field="*{name}" th:value="*{name}" class="form-control" id="nameInput"/>
                        <div class="alert alert-warning" role="alert" th:if="${#fields.hasErrors()}" th:errors="*{name}"></div>
                    </div>
                    <div class="form-group">
                        <label for="numberInput">Phone number:</label>
                        <input type="text" th:field="*{number}" th:value="*{number}" class="form-control" id="numberInput"/>
                        <div class="alert alert-warning" role="alert" th:if="${#fields.hasErrors()}" th:errors="*{number}"></div>
                    </div>
                    <div class="form-group text-right">
                        <button type="submit" class="btn btn-success">Confirm</button>
                        <a class="btn btn-danger" th:href="@{/contacts}" role="button">Cancel</a>
                    </div>
                </form>
            </div>
        </div>
    </div>

</body>
</html>
答案

您需要一个包含id值的隐藏输入字段。

<div class="form-group">
    <label for="idText">Identifier (automaticaly generated):</label>
    <strong id="idText" th:text="${contact.getId()}"></strong>
    <input id="id" th:field="*{id}" type="hidden"/> 
</div>
另一答案

我想帮助您,但我不知道您是否使用相同的对象将数据保存在您的表(您的实体)中,并在控制器中返回您的视图模型。通常,您应该使用不同的对象并将其映射到您的服务中。如果您使用相同的对象,则可能会遇到问题。

以上是关于Thymeleaf视图不会将实体ID传递给Spring @Controller,而是将其与其他属性一起传递的主要内容,如果未能解决你的问题,请参考以下文章

使用 Thymeleaf 和 Spring Boot 将我的 HTML 中的整数数组传递给控制器

JPQL订单实体通过将ID传递给IN子句

如何将 NSManagedObject 传递给 NSPredicate 以及如何保存一对多的实体

Thymeleaf 将对象集作为对象的成员传递给控制器

如何使用 ajax 将 id 传递给部分视图控制器方法?

将模板中的按钮中的 id 传递给 Django 视图