我正在使用 SpringData 的存储库。如果我尝试通过不存在或从未存在过的 ID 删除实体,则会引发异常。由于我不想在删除实体之前检查该实体是否存在,因此最好它会默默地失败。这会让事情变得更容易,因为可观察的行为是相同的 - 调用后实体不再存在。不管它被删除了还是根本不存在,我不在乎。
有没有办法修改
delete(EntityId)
的默认行为,以便在实体不存在时不会抛出异常?
SpringData的delete文档说,如果实体不存在,它将抛出异常。
更新答案(否决后)
我原来的答案(如下)实际上是错误的:我对这个问题的理解也受到官方 JavaDoc 中缺少对
EmptyResultDataAccessException
的引用的影响(正如 Adrian Baker 在他的评论中所报道的)。
因此,山城 Rion 提出的解决方案可能是解决此问题的更好方法
if (repository.existsById(entityId)) {
repository.deleteById(entityId);
}
或这个(没有
if
,但可能表现更差):
repository.findById(entityId)
.map(repository::delete)
原(错误)答案
JavaDocs 表示,如果提供的参数(id、实体、
IllegalArgumentException
)为 null,则将抛出 Iterable<T>
,如果实体不存在,则不会抛出。
如果您需要避免 IllegalArgumentException
,您可以实现一个自定义删除方法来检查
id != null
:
public void customDelete(ID id) {
if(id != null){
this.delete(id);
}
}
如果您不知道如何添加
deleteById
方法:
@Modifying
@Query("DELETE FROM <entity> WHERE ID = ?1")
public void deleteById(<IdType> id);`
如果更适合您,您还可以选择本机查询:
@Modifying
@Query(nativeQuery=true, value="DELETE FROM MY_TABLE WHERE ID = ?1")
public void deleteById(IdPrimitiveType id);`
Integer
:
Integer deleteMyEntityById(Long id);
如果要删除的实体不存在,则如果该实体已被删除,您的方法将返回 0 或 1。
All
添加到方法名称中。使用
void deleteAllById(ID id)
代替
delete(ID) or deleteById(ID)
。这个方法应该是你自己定义的,它不是来自spring内置的
CRUDRepository
。
这个方案是可行的,但是是否符合spring data规范,看评论自行判断。
JpaRepository
您可以轻松删除实体(如果存在)。在此示例中
PostsRepository
扩展了
JpaRepository
:
if (postsRepository.existsById(postId)) {
postsRepository.deleteById(postId);
}
repository.deleteAllByIdInBatch(ids);
相同
repository.deleteAllById(ids);
id
@Transactional
@Override
public void delete(ID id) {
T entity = findOne(id);
if (entity == null) {
//do something instead of throwing exception ex:
//syso entity does not exist ; return;
}
em.remove(em.merge(entity));
}
@javax.persistence.Entity
@Table(name = "mytable")
@Proxy(lazy = false)
@SQLDelete(
sql =
"DELETE FROM mytable " +
"WHERE my_id = ?"
)
public class MyTable {
@javax.persistence.Column(name = "my_id", nullable = false)
@Id
private Long id;
...
}
然后 hibernate 会自动替换 '?'在准备好的语句中,具有 MyTable 对象的实际 id,该对象映射到表的 SQL 字段“my_id”
在这种情况下,如果表中的记录不存在,则不会抛出异常,只会默默删除 0 行,就像普通 SQL DELETE 查询一样
if (postsRepository.existsById(postId)) {
throw new EntityNotFoundExceptionById("Invlaid Id was provided");
}
postsRepository.deleteById(postId);
EntityNotFoundExceptionById 类
@ResponseStatus(HttpStatus.NOT_FOUND)
public class EntityNotFoundExceptionById extends RuntimeException {
public EntityNotFoundExceptionById(String message) {
super(message);
}
}
if(repsoitory.existsById(id)){
repository.deleteById(id)
}
如果你有要删除的 ids 列表,你可以使用 java 8
List<Long> ids=new ArrayList<>();
ids.stream().filter(id->repository.existsById(id))
.forEach(id->repository.deleteById(id));