Spring JPA 不能删除 id 为 0 的数据
Spring Data JPA 的 Repository 不能删除 id 为数值类型(Integer、Long 等),且值为 0 的对象
源码中逻辑是,如果 ((Number)id).longValue() == 0L,则跳过删除
(源码中这样写,具体原因目前不清楚)
Debug 流程如下:
SimpleJavaRepository.java 是默认的 JpaRepository 实现,其中delete 代码如下
@Transactional
public void delete(T entity) {
Assert.notNull(entity, "Entity must not be null!");
if (!this.entityInformation.isNew(entity)) { // <<<- Debug 进 isNew 方法
Class<?> type = ProxyUtils.getUserClass(entity);
T existing = this.em.find(type, this.entityInformation.getId(entity));
if (existing != null) {
this.em.remove(this.em.contains(entity) ? entity : this.em.merge(entity));
}
}
}
this.entityInformation.isNew(entity) 这句在 JpaMetamodelEntityInformation.java 中:
public boolean isNew(T entity) {
if (this.versionAttribute.isPresent() && !(Boolean)this.versionAttribute.map(Attribute::getJavaType).map(Class::isPrimitive).orElse(false)) {
BeanWrapper wrapper = new DirectFieldAccessFallbackBeanWrapper(entity);
return (Boolean)this.versionAttribute.map((it) -> {
return wrapper.getPropertyValue(it.getName()) == null;
}).orElse(true);
} else {
return super.isNew(entity); // <<<- Debug 进 isNew 方法
}
}
再往下走,AbstractEntityInformation.java
public boolean isNew(T entity) {
ID id = this.getId(entity);
Class<ID> idType = this.getIdType();
if (!idType.isPrimitive()) {
return id == null;
} else if (id instanceof Number) {
return ((Number)id).longValue() == 0L; // <<<- 在这里返回 true
} else {
throw new IllegalArgumentException(String.format("Unsupported primitive id type %s!", idType));
}
}
isNew 方法在判断 ((Number)id).longValue() == 0L 时返回了 ture,所以 delete 方法跳过了删除