我正在与 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:/";
}
有人可以帮我解释一下为什么会这样吗?可以通过其他方式避免吗?
我建议将实体与表单数据对象分开。
因此,创建一个
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 处理表单了解更多信息。