Spring Data执行删除请求时先插入后删除?Spring Boot接口异常排查
我之前碰到过类似的问题,结合你给出的Hibernate日志来看,出现删除请求触发插入操作的情况,大概率是下面这些原因导致的:
实体状态误判引发意外保存
当你处理删除请求时,可能不小心调用了save()或saveAndFlush()方法,而传入的Registration实体处于transient状态——也就是没有设置有效的主键ID,或者ID在数据库中不存在。Hibernate会把这种状态的实体认定为新对象,自动执行插入操作。
举个例子:如果你从请求参数里新建了一个Registration对象,只设置了要匹配删除的字段但没给正确的ID,或者ID被设成了无效值,这时候如果在调用delete()之前触发了保存操作,就会出现先插后删(甚至只插不删)的情况。级联操作的副作用
如果你的Registration实体和其他实体配置了级联关系(比如@OneToMany或@ManyToMany里设置了cascade=CascadeType.ALL,或者包含PERSIST类型的级联),当你删除关联实体时,Hibernate可能会先尝试保存处于transient状态的Registration实体,之后再执行删除操作。
建议检查下你的实体类,看看是不是存在不必要的级联保存配置,导致删除时触发了关联实体的插入。主键生成策略的问题
从日志里的select max(id) from registration可以看出来,你的主键ID用的是基于表的生成策略(比如GenerationType.TABLE)。如果在删除操作时,实体对象的ID被意外重置或者没有正确设置,Hibernate会自动去查询当前最大ID来生成新的主键,随后执行插入操作。
比如你可能在删除前对实体做了一些修改,不小心清空了ID字段,导致Hibernate误以为这是个新实体,进而触发插入。业务逻辑的调用错误
有可能是你在代码里误把删除方法写成了保存方法,或者在删除操作之前调用了其他会触发实体保存的方法(比如merge())。建议仔细检查你的Service层代码,梳理删除请求的处理流程,看看是不是有步骤逻辑错误。
排查建议
- 先核对删除接口的代码,确认没有在删除前调用
save()/saveAndFlush()这类保存方法; - 查看
Registration实体的@GeneratedValue注解,确认主键生成策略和ID的设置逻辑是否正确; - 检查实体间的级联配置,移除不必要的级联保存类型;
- 开启Hibernate的完整日志(包括事务和实体状态变更),追踪实体在操作前后的状态变化,定位触发插入的具体步骤。
内容的提问来源于stack exchange,提问作者Billy

