问题描述
使用Jpa repository save函数去更新已有实体时,会报错:executeUpdate raise “Duplicate entry for primary key”。查找网络资料发现并不应该出现这个错误,Jpa repository在save已实体时如果发现数据库中有既存的主键,那么应该自动更新这个实体而不应该报主键冲突的错误,至此问题陷入了死结…
原因分析
经过仔细排查,发现问题出在了数据拷贝的过程上:
- 首先Controller接受前端发来的DTO
- 将DTO转化为entity,问题就出在这一步,由于entity是有Audit审计和乐观锁控制的,因此没有created_by、created_date、modified_by、modified_date、version这些字段,而再把DTO转化为entity的过程中只是简单的BeanUtils.copyProperties,因此由DTO转化而来的entity的version字段是null
- 使用Jpa repository保存entity的过程中,由于version字段是null,导致写数据时乐观锁保存失败。但是尚没有研究清楚为什么报错是Duplicate entry for primary key而非乐观锁的相关错误,还待后续学习排查。
解决方法
在BeanUtils.copyProperties过程中自定义BeanUtils.copyProperties(entity, entityInDB, CustomBeanUtils.getNullPropertyNames(entity));排除entity中Null字段的拷贝。