Thymeleaf hidden域失效 Spring Boot编辑时新增实体问题
问题根因
Spring Data JPA的save()方法判断逻辑非常直白:传进去的实体主键有值就更新对应记录,主键是null就直接新增一条。你现在出现编辑后新增记录的问题,本质就是后端拿到的提交对象里idState主键是null,和你怀疑的隐藏域传值问题直接相关,按下面的顺序排查,10分钟就能修好:
排查修复步骤
1. 先查前端表单和编辑跳转接口的传值逻辑
首先打开states_form.html,确认两个点:
- 表单标签必须用
th:object绑定后端传过来的State实体,隐藏域必须放在这个form标签内部,否则th:field不会生效:<form th:action="@{/states/save}" th:object="${state}" method="post"> <input type="hidden" th:field="*{idState}"> <!-- 剩下的州名、编码等业务字段正常写即可 --> </form> - 打开
StateController里跳转到编辑页的接口,绝对不能传一个空的new State()给前端,必须从数据库查出带主键的现有对象放到Model里:
这是最高发的错误点:很多人写编辑接口的时候图省事,new了个空对象传前端,隐藏域自然拿不到id值,提交回去主键就是null。@GetMapping("/states/edit/{id}") public String editForm(@PathVariable Integer id, Model model) { State existState = stateService.getById(id); // 查出来的对象自带idState值 model.addAttribute("state", existState); return "states_form"; }
2. 查State实体类的配置
打开State的POJO类,检查两个点:
- 主键注解配置正确,要和PostgreSQL的主键生成策略匹配:
第二高发错误:用了Lombok但是没加@Entity @Table(name = "state") public class State { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) // 如果用PG序列就改成对应SEQUENCE策略 @Column(name = "id_state") private Integer idState; // 重点:必须给idState加setter方法!否则Spring MVC接收到参数也没法给字段赋值 public Integer getIdState() {return idState;} public void setIdState(Integer idState) {this.idState = idState;} // 其他字段、getter/setter正常编写 }@Data注解,或者手写getter/setter的时候漏了idState的set方法,前端明明传了id,后端接不住,实体主键还是null。
3. 查保存接口的逻辑
打开处理表单提交的save接口,不要自己手动new对象覆盖了绑定的id:
@PostMapping("/states/save") public String doSave(State state) { // 不要在这里写state.setIdState(null),也别自己new State()再挨个set属性 stateService.save(state); return "redirect:/states"; }
4. 10秒定位问题点
打开浏览器F12,提交编辑表单的时候看网络请求里的载荷(Form Data):
- 如果载荷里根本没有
idState这个参数:回去查第一步的表单绑定、编辑接口传值问题 - 如果载荷里有idState参数,但是后端接收到的是null:查实体类字段名是否匹配(注意大小写,参数名是idState就不要把字段写成IdState、idstate)、有没有漏写setter
验证方法
改完在save方法里加一行临时打印:
System.out.println("提交的实体ID:" + state.getIdState());
只要控制台打印出来的是你编辑的那条记录的ID,不是null,调用save就一定会走更新,不会再生成新记录。
内容的提问来源于stack exchange,提问作者iank
相关产品推荐
相关产品推荐

