【发布时间】:2021-08-18 09:39:41
【问题描述】:
主要问题
在我的 Web 应用程序中,使用 Spring/Hibernate/Thymeleaf 实现,我有两个域对象,所有者和宠物。 Pet 对象有一个(可选的)Owner 字段。在通过网络表单更新宠物期间,用户可以输入存在(在数据库中)或不存在的所有者 ID。
当用户使用现有的所有者 ID 更新宠物时,会找到现有的所有者对象并将其与宠物相关联。 但是,当用户使用数据库中不存在的所有者 ID 更新宠物时,返回的宠物对象(在“POST”控制器方法中)具有空所有者对象。此外,由于宠物域中的所有者字段可以为空,因此不会引发验证错误。
最终,这可能会导致用户提交错误的值,认为他们添加了一个所有者,只是为了让宠物的更新实际发生在一个空所有者的情况下(如果没有正确捕获)。
我的问题是,在执行父对象更新之前验证嵌套对象的 id 存在的推荐方法是什么。
进一步的想法:
- 我看到了一个相关问题:spring mvc nested model validation,建议在其中添加自定义验证器。在我的情况下,添加一个自定义验证器,它将在 PetController 中运行并验证 Pet/Owner 对象,我认为这不起作用。返回的宠物对象包含一个空所有者对象,这是一个完全有效的状态。我需要在数据绑定期间进行验证。一旦我们进入控制器,绑定后,所有者对象为空,并且不会对表单值进行验证。
- 我已经通过添加自定义格式化程序(从字符串到所有者)对其进行了一些工作。如果无法找到所有者 id,则此格式化程序将返回一个新的所有者对象,其 id 为“未找到”(或在这种情况下为一些数字/整数等价物)。在我的控制器中,我可以检查具有“错误 id”的所有者并引发错误。但是,不返回对象的默认行为似乎更安全,因为我的自定义格式化程序实际上返回了一个无效对象(这可能会导致其他问题?)。
代码
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Pet {
@Id
private int id;
private String name;
@ManyToOne
@Valid
private Owner owner;
}
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Owner {
@Id
@NotNull
@NonNull
private int id;
private String firstName;
private String lastName;
}
@Controller
public class PetController {
@Autowired
PetRepository petRepository;
@RequestMapping("editPet")
@GetMapping
public String editPet(Model model) {
Pet pet = petRepository.getById(1);
model.addAttribute("pet", pet);
return "editPet";
}
@RequestMapping("updatePet")
@PostMapping
public String updatePet(@Validated Pet pet, BindingResult bindingResult) {
petRepository.save(pet); // if the user submits an invalid owner id, the returned pet will have a null owner
// object, but no error raised.
return "editPet";
}
}
}
【问题讨论】:
标签: java spring validation spring-mvc