带有post请求的表单将请求参数分配给绑定到表单的对象

问题描述 投票:0回答:1

我正在与 Thymeleaf 和 Spring 合作,但发生了一些意想不到的事情。

我有这个联系课程:

@Entity
public class Contact {
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CONTACT_ID_GEN")
    @SequenceGenerator(name="CONTACT_ID_GEN", sequenceName = "CONTACT_ID_GEN")
    private long id;
    @NotBlank
    private String name;
    @NotNull
    @OneToMany(mappedBy = "contact", fetch=FetchType.EAGER, cascade = CascadeType.ALL)
    private List<ContactInfo> info;

    //Constructors getter setters etc.
}

具有此联系信息类的嵌套列表:

@Entity
public class ContactInfo {
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CONTACT_INFO_ID_GEN")
    @SequenceGenerator(name="CONTACT_INFO_ID_GEN", sequenceName = "CONTACT_INFO_ID_GEN")
    private long id;
    @Column(name = "INFO_VALUE")
    private String infoValue;
    private InfoType infoType;
    @ManyToOne
    @JoinColumn(name = "FK_CONTACT_ID")
    private Contact contact;

    //Constructors getter setters etc.
}

我的挑战是制作一个可以添加新联系信息对象的表单,但这一切都必须通过联系人。

使用Thymeleaf和Spring,这是我想出的表单声明

<form th:action="'/add-new-contact-info/' + ${contact.id}" method="post" th:object="${newContactInfo}">

这里,newContactInfo是一个contactInfo类型的空对象,contact.id是父联系人对象的id。

这个想法是,如果我想为 id 为 1 的 Cpntact 添加 contactInfo 对象,它将转到 /add-new-contact-info/1

现在我的表单只有 infoValue 和 infoType 的输入。没有 id 输入字段。

我希望 ID 为 0 作为默认值,然后一旦我调用存储库的 save 方法,它将使用该序列生成一个新的。

但相反,Thymeleaf 始终为 id 提供路径中的值。因此,对于 /add-new-contact-info/{id},接收到的 ContactInfo 对象的 id 将为 {id}。

我以前使用过 Spring,但没有使用过 Thyemleaf,而且我从未见过任何类似的东西。通常 bodyResponse 对象的值仅由表单中的值组成,路径中的值应该是单独的,不是吗?

我找到了一个修复程序,只需在代码中立即手动将 id 设置为 0,效果就很好。其他和我做了同样事情的人只是将 id 的名称更改为 contactInfoId,这也有效。

这是我通过使用“contactInfo.setId(0);”在控制器中将 id 设置为 0 来修复它的方法。线路:

@PostMapping("/add-new-contact-info/{id}")
public String makeNewContactInfo(ContactInfo contactInfo, @PathVariable long id, Model model,
        RedirectAttributes redirectAttributes) {
    contactInfo.setId(0);
    Optional<Contact> optRes = contactService.readById(id);
    if (optRes.isPresent()) {
        Contact contact = optRes.get();
        contact.getInfo().clear();
        contact.getInfo().add(contactInfo);
        return this.updateContact(contact);
    }
    String message = "Contact doesn't exist";
    redirectAttributes.addFlashAttribute("message", message);
    return "redirect:/";
}

有人可以帮我解释一下为什么会这样吗?可以通过其他方式避免吗?

java spring spring-mvc spring-data-jpa thymeleaf
1个回答
0
投票

我建议将实体与表单数据对象分开。

因此,创建一个

AddContactInfoFormData
对象来表示 Thymeleaf 表单中的字段。

在您的 POST 映射中,您将执行以下操作:

@PostMapping("/add-new-contact-info/{id}")
public String makeNewContactInfo(@Valid @ModelAttribute("formData") AddContactInfoFormData formData, BindingResult bindingResult, @PathVariable long id, Model model,
        RedirectAttributes redirectAttributes) {

  if (bindingResult.hasErrors()) {
    return "contacts/edit" // This should be the name of your Thymeleaf template so it is re-rendered with the errors
  }


    Optional<Contact> optRes = contactService.readById(id);
    if (optRes.isPresent()) {
        Contact contact = optRes.get();
        contact.replaceInfo(formData.toContactInfo());      
        return this.updateContact(contact);
    }
    String message = "Contact doesn't exist";
    redirectAttributes.addFlashAttribute("message", message);
    return "redirect:/";
}

AddContactInfoFormData
将有一个
toContactInfo()
方法,根据收到的表单数据信息创建
ContactInfo
的新实例。

请参阅使用 Thymeleaf 处理表单了解更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.