Spring Boot Web整合JPA、JSP+JSTL更新表单@Id类型转换错误求助
问题根本原因
错误的核心是控制器方法的参数顺序错误:Spring MVC要求BindingResult参数必须紧挨着它要校验的@ModelAttribute参数,中间不能插入其他参数。你当前的代码里Model参数插在了Quote实体和BindingResult中间,导致Spring参数绑定错位:本来要绑定到quote字段的文本内容,被误当成了Quote实体的id值做类型转换,所以抛出NumberFormatException,请求直接被拦截,无法进入控制器方法。
修复步骤
1. 调整控制器参数顺序
把QuoteController里的方法参数调整为BindingResult紧跟@ModelAttribute,修正后的代码如下:
@RequestMapping(value = "/update",method = RequestMethod.POST) public String updateQuote(@ModelAttribute("quote") Quote quote, BindingResult bindingResult, Model model) { LOGGER.info("/update POST request received, quote :: " + quote); if (bindingResult.hasErrors()) { LOGGER.error("/update POST request has errors :: " + bindingResult.getAllErrors()); model.addAttribute("error", bindingResult.getAllErrors()); return "qms/edit"; } quoteService.updateQuote(quote); return "qms/list"; }
调整后参数绑定会恢复正常,隐藏域的id值会正确绑定到Quote实体的id字段,不会再出现类型转换错误。
2. DTO方案的问题解决
如果你要使用DTO做参数接收,不需要移除id字段,保留id字段即可:
- 编辑页的隐藏域正常传递id值到DTO的id属性
- 转换实体的时候,先通过DTO的id从数据库查询出原有实体,再把DTO的非id属性拷贝到查询到的实体对象上,再调用save方法,此时JPA会识别到实体有id,执行更新操作而非新增,示例逻辑:
// service层更新逻辑 public void updateQuote(QuoteDTO dto) { Quote existingQuote = quoteRepository.findById(dto.getId()) .orElseThrow(() -> new RuntimeException("对应记录不存在")); // 拷贝属性,忽略id字段避免被覆盖 BeanUtils.copyProperties(dto, existingQuote, "id"); quoteRepository.save(existingQuote); }
内容的提问来源于stack exchange,提问作者itsraghz
相关产品推荐
相关产品推荐

