Thymeleaf表单实现部分表更新及@OneToMany持久化验证问题
问题2:验证失败后UserDetails变为null的解决方法
无需额外手动查询,只需在验证失败时恢复关联的userDetailsById集合即可。
原因
Spring MVC绑定表单数据时,仅会填充表单中存在的字段,userDetailsById未在表单中声明,因此提交后的User对象中该集合为null;而初始加载的User是从数据库查询的完整对象,包含关联数据。
解决方案
采用问题1中的方案,验证失败时使用从数据库加载的原始User对象,该对象自带关联的userDetailsById集合,页面即可正常遍历显示。
额外优化:将User实体中的Collection<UserDetails>改为List<UserDetails>并初始化空集合,避免null指针:
@OneToMany(mappedBy = "userByUser") private List<UserDetails> userDetailsById = new ArrayList<>();
问题3:传递UserDetails的comment并持久化
针对新增UserDetails记录的场景,建议通过普通请求参数接收comment,在Controller中创建UserDetails对象并关联到User后单独保存。
步骤1:修改表单
将原UserDetails输入框改为普通参数,无需绑定到User对象:
<div class="row"> <div class="col"> <div class="mt-3"> <label class="form-label" for="userDetail">User Details</label> <input class="form-control" id="userDetail" type="text" name="comment"> </div> </div> </div>
步骤2:修改Controller方法
接收comment参数,非空则创建并保存UserDetails:
@PostMapping("/save") public String saveUser(@Valid User submittedUser, BindingResult result, @RequestParam(value = "comment", required = false) String comment, Model model) { if (result.hasErrors()) { User originalUser = userRepository.findById(submittedUser.getId()).orElse(submittedUser); originalUser.setAge(submittedUser.getAge()); originalUser.setBirthplace(submittedUser.getBirthplace()); model.addAttribute("user", originalUser); return "user"; } // 保存User User savedUser = userRepository.save(submittedUser); // 新增评论 if (comment != null && !comment.isEmpty()) { UserDetails userDetails = new UserDetails(); userDetails.setUser(savedUser.getId()); userDetails.setComments(comment); userDetailsRepository.save(userDetails); } return "redirect:/all"; }
可选规范方案:使用DTO
若需对UserDetails字段做验证,可创建包含User和新comment的DTO,统一管理验证规则:
@Data public class UserUpdateDTO { @Valid private User user; @NotEmpty(message = "Comment cannot be empty") private String newComment; }
后续表单绑定到DTO,Controller接收DTO并处理即可。
内容的提问来源于stack exchange,提问作者Stephen
相关产品推荐
相关产品推荐

